Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When making a table for dates in R, how can I fill in the missing dates to appear as having a frequency of 0?

Tags:

r

Suppose you have the following table:

Student<-c("Bob", "Joe", "Sam", "John")
ClassDate<-as.Date(c("2020-01-01", "2020-01-01", "2020-01-02", "2020-01-05"), "%Y-%m-%d")
df<-data.frame(Student=Student, ClassDate=ClassDate)
df

  Student  ClassDate
1     Bob 2020-01-01
2     Joe 2020-01-01
3     Sam 2020-01-02
4    John 2020-01-05

When you make a cumulative frequency table for ClassDate, you get the following:

data.frame(cumsum(table(df$ClassDate)))

           cumsum.table.df.ClassDate..
2020-01-01                           2
2020-01-02                           3
2020-01-05                           4

However, what I'm looking for is the following which still includes the missing dates

           cumsum.table.df.ClassDate..
2020-01-01                           2
2020-01-02                           3
2020-01-03                           3
2020-01-04                           3
2020-01-05                           4
like image 749
GM01 Avatar asked Feb 24 '21 21:02

GM01


1 Answers

An option is to create a column of 1s, expand the data with complete by creating a sequence from minimum to maximum value of 'ClassDate' by 'day' while filling the 'n' with 0, then do a group by sum on the 'n' column, and do the cumsum

library(dplyr)
library(tidyr)
df %>% 
   mutate(n = 1) %>% 
   complete(ClassDate = seq(min(ClassDate), max(ClassDate),
            by = '1 day'), fill = list(n = 0)) %>% 
   group_by(ClassDate) %>% 
   summarise(n = sum(n), .groups = 'drop') %>% 
   mutate(n = cumsum(n))

-output

# A tibble: 5 x 2
#  ClassDate      n
#* <date>     <dbl>
#1 2020-01-01     2
#2 2020-01-02     3
#3 2020-01-03     3
#4 2020-01-04     3
#5 2020-01-05     4

In base R, an option is also to specify the levels while converting to factor

v1 <- with(df, factor(ClassDate, levels = 
  as.character(seq(min(ClassDate), max(ClassDate), by = '1 day'))))
data.frame(Cumsum = cumsum(table(v1)))
like image 167
akrun Avatar answered Oct 02 '22 14:10

akrun