How to fill an empty dataframe with default values using dplyr?

I get this correct output running the code immediately beneath it, counting the number of times"A" appears in the Element column of the myData data frame:

  Element counted
1       A       4

Code for above output:

library(dplyr)

myData = data.frame(Element = c("A","A","C","A","B","B","A"),Class = c(0,0,0,0,1,1,2))

myData %>% 
  filter(Element == 'A') %>%
  count(Element, name = 'counted')

However, I'd like to change the code so it returns the dataframe with count of 0 when it is run against a non-existing element. I need this for a series of ifelse(...) statements that look back at that myData dataframe. So, when running this code for an element D that doesn't exist:

myData %>% 
  filter(Element == 'D') %>%
  count(Element, name = 'counted')

I'd like to get back:

  Element counted
1       D       0

Instead of this which the code currently generates:

[1] Element counted
<0 rows> (or 0-length row.names)

In the complete code the D is an unknown, falling outside elements A - C. I'd like to return the 0 for any element outside A -C. I'd like to do this without including the element "D" in the factor levels.

Is there a slick way to this in dplyr?

Upvotes: 3

Views: 449

Answers (1)

Darren Tsai
Darren Tsai

Reputation: 35554

Convert Element to factor and give all levels you want, then set .drop = FALSE in count():

myData %>%
  mutate(Element = factor(Element, levels = c('A', 'B', 'C', 'D'))) %>%
  count(Element, .drop = FALSE)

#   Element n
# 1       A 4
# 2       B 2
# 3       C 1
# 4       D 0

Update

It seens that you want to check whether a element is included in Element. If it is, then count its amount; otherwise, print 0. You could assign elements you wan to check outside and use the following code:

x <- c('A', 'D')

myData %>%
  filter(Element %in% x) %>% 
  mutate(Element = factor(Element, levels = x)) %>%
  count(Element, .drop = FALSE)

#   Element n
# 1       A 4
# 2       D 0

Supplement

.drop is actually an argument in group_by(). This line

%>% count(Element, .drop = FALSE)

is equivalent to

%>% group_by(Element, .drop = FALSE) %>% tally()

under the hood. And tally can also be traced back to summarise(n = n()).

Upvotes: 4

Related Questions