2016-08-02 44 views
1

我的数据是这样的,并已进行排序:用相同的ID创建一个包含以前的值新列

> 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

以前的值还是下一个值?您的输出是下一个值。如果它是以前的值,则使用'lag'而不是'lead' – Sumedh

+0

我的意思是'previous',因为我的数据实际上是按降序排列的。 – Scarabee

回答

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 
+0

谢谢,这是我的数据集上最快的方法。 – Scarabee

1

这里是一个基R法与avetail

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 
2

我们可以使用data.table。将'data.frame'转换为'data.table'(setDT(df)),按'id'分组,我们将'x'中的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 
相关问题