我的数据看起来像这样,已经排序了:
> dput(df)
structure(list(id = c(1, 2, 3, 3, 2, 2, 1), x = c(20, 40, 70,
70, 80, 40, 70)), .Names = c("id", "x"), row.names = c(NA, -7L
), class = "data.frame")
> df
id x
1 1 20
2 2 40
3 3 70
4 3 70
5 2 80
6 2 40
7 1 70
我需要创建一个新列,其中包含x
的前一个值id
。所以结果应该是:
> df
id x old_x
1 1 20 70
2 2 40 80
3 3 70 70
4 3 70 NA
5 2 80 40
6 2 40 NA
7 1 70 NA
我可以这样做:
for (i in 1:nrow(df)){
id0 = df$id[i]
j = i + match(id0 , df$id[i+1:nrow(df)])
df$old_x[i] = df$x[j]
}
但它太慢了。最好的方法是什么?
感谢您的帮助!
答案 0 :(得分:3)
使用dplyr
:
library(dplyr)
df %>% group_by(id) %>% mutate(old_x = lead(x))
#Source: local data frame [7 x 3]
#Groups: id [3]
# id x old_x
# <dbl> <dbl> <dbl>
#1 1 20 70
#2 2 40 80
#3 3 70 70
#4 3 70 NA
#5 2 80 40
#6 2 40 NA
#7 1 70 NA
答案 1 :(得分:2)
我们可以使用data.table
。将'data.frame'转换为'data.table'(setDT(df)
),按'id'分组,我们将':=
中的lead
值分配给'old_x ”。这应该非常快,因为我们正在分配。
library(data.table)
setDT(df)[,old_x := shift(x, type = "lead") , by = id]
df
# id x old_x
#1: 1 20 70
#2: 2 40 80
#3: 3 70 70
#4: 3 70 NA
#5: 2 80 40
#6: 2 40 NA
#7: 1 70 NA
答案 2 :(得分:1)
以下是包含ave
和tail
的基本R方法:
df$old_x <- ave(df$x, df$id, FUN=function(i) c(tail(i, -1), NA))
df
id x old_x
1 1 20 70
2 2 40 80
3 3 70 70
4 3 70 NA
5 2 80 40
6 2 40 NA
7 1 70 NA