加快逐行比较

时间:2017-03-30 11:23:46

标签: r dataframe data.table dplyr vectorization

我有data.frame,如下所示:

id year  x y         v1
 1 2006 12 1  0.8510703
 1 2007 12 1  0.5954527
 1 2008 12 2 -1.9312854
 1 2009 12 1  0.1558393
 1 2010  8 1  0.9051487
 2 2001 12 2 -0.5480566
 2 2002 12 2 -0.7607420
 2 2003  3 2 -0.8094283
 2 2004  3 2 -0.1732794

我想在id和{{1}时总结(按v1x连续年份(因此分别为2010年和2009年,2009年和2008年等) }} 比赛。预期产出:

y

最早的id year res 1 2010 NA 1 2009 NA 1 2008 NA 1 2007 1.4465230 2 2004 -0.9827077 2 2003 NA 2 2002 -1.3087987 year被移除,因为前一年没有。

我有一个缓慢的id解决方案,但我希望加快速度,因为我的数据相当大。

数据:

lapply

当前解决方案:

set.seed(1)
dat <- data.frame(id = c(rep(1,5),rep(2,4)),year = c(2006:2010,2001:2004),
                x = c(12,12,12,12,8,12,12,3,3), y = c(1,1,2,1,1,2,2,2,2),
                v1 = rnorm(9))

2 个答案:

答案 0 :(得分:4)

我认为这是一个data.table解决方案。

datNew <- setDT(dat)[, .(year=year, res=(v1+shift(v1)) * NA^(x != shift(x) | y != shift(y))),
                     by=id][-1, .SD, by=id][]
   id year        res
1:  1 2007 -0.4428105
2:  1 2008         NA
3:  1 2009         NA
4:  1 2010         NA
5:  2 2001         NA
6:  2 2002 -0.3330393
7:  2 2003         NA
8:  2 2004  1.3141061

这里,j语句包含一个包含两个元素的列表,年份和函数。此函数使用shift将值与滞后值相加,但乘以NA或1,具体取决于x和y是否与其滞后值匹配。该计算由id执行。输出被送到第二个链,它会丢弃每个id的第一个观察结果,即所有NA。

如果需要,您可以使用setorder有效调整订单。

setorder(datNew, id, -year)

datNew
   id year        res
1:  1 2010         NA
2:  1 2009         NA
3:  1 2008         NA
4:  1 2007 -0.4428105
5:  2 2004  1.3141061
6:  2 2003         NA
7:  2 2002 -0.3330393
8:  2 2001         NA

答案 1 :(得分:0)

假设示例中有分类年份:

dat %>% 
  group_by(id) %>% 
  mutate(res = v1 + lag(v1),                                     #simple lag for difference                            
         res = ifelse(x == lag(x) & y == lag(y), v1, NA)) %>%    #NA if x and y don't match
  slice(-1)                                                      #drop the first year

如果需要,您可以在结尾使用%>% select(id, year, res)%>% arrange(id, desc(year))