我有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}时总结(按v1
)x
连续年份(因此分别为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))
答案 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))
。