dplyr into data.table:过滤器>分组依据>计数

时间:2019-07-19 19:14:53

标签: r dplyr data.table

我通常使用dplyr,但面对的数据集很大,而且我的方法非常慢。我基本上需要按日期过滤df组,并计算

样本数据(已经将所有内容转换为data.table

library(data.table)
library(dplyr)

set.seed(123)

df <- data.table(startmonth = seq(as.Date("2014-07-01"),as.Date("2014-11-01"),by="months"),
                 endmonth = seq(as.Date("2014-08-01"),as.Date("2014-12-01"),by="months")-1)


df2 <- data.table(id = sample(1:10, 5, replace = T),
                  start = sample(seq(as.Date("2014-07-01"),as.Date("2014-10-01"),by="days"),5),
                  end = df$startmonth + sample(10:90,5, replace = T)
)

#cross joining
res <- setkey(df2[,c(k=1,.SD)],k)[df[,c(k=1,.SD)],allow.cartesian=TRUE][,k:=NULL]

我的dplyr方法有效,但是很慢

res %>% filter(start <=endmonth & end>= startmonth) %>% 
  group_by(startmonth,endmonth) %>% 
  summarise(countmonth=n()) 

我的data.table知识是有限的,但我想我们会setkeys()在日期列和类似res[ , :=( COUNT = .N , IDX = 1:.N ) , by = startmonth, endmonth]的位置上按组进行计数,但是我不确定过滤器如何进行在那里。

感谢您的帮助!

1 个答案:

答案 0 :(得分:4)

您可以在联接中进行计数:

df2[df, on=.(start <= endmonth, end >= startmonth), allow.cartesian=TRUE, .N, by=.EACHI]

        start        end N
1: 2014-07-31 2014-07-01 1
2: 2014-08-31 2014-08-01 4
3: 2014-09-30 2014-09-01 5
4: 2014-10-31 2014-10-01 3
5: 2014-11-30 2014-11-01 3

或将其添加为df中的新列:

df[, n := 
  df2[.SD, on=.(start <= endmonth, end >= startmonth), allow.cartesian=TRUE, .N, by=.EACHI]$N
]

工作原理。语法为x[i, on=, allow.cartesian=, j, by=.EACHI]。如果i的每一行都用于在x中查找值。符号.EACHI表示将对j=.N的每一行进行汇总(i)。