【发布时间】:2018-11-06 01:05:56
【问题描述】:
我有以下按名称和时间排序的数据框。
set.seed(100)
df <- data.frame('name' = c(rep('x', 6), rep('y', 4)),
'time' = c(rep(1, 2), rep(2, 3), 3, 1, 2, 3, 4),
'score' = c(0, sample(1:10, 3), 0, sample(1:10, 2), 0, sample(1:10, 2))
)
> df
name time score
1 x 1 0
2 x 1 4
3 x 2 3
4 x 2 5
5 x 2 0
6 x 3 1
7 y 1 5
8 y 2 0
9 y 3 5
10 y 4 8
在df$score 中有零后跟未知数量的实际值,即df[1:4,],有时两个df$score == 0 之间有重叠的df$name,即df[6:7,]。
我想将df$time 更改为df$score != 0。具体来说,如果df$name 匹配,我想用df$score == 0 分配最近的上一行的时间值。
以下代码提供了良好的输出,但我的数据有数百万行,因此此解决方案效率非常低。
score_0 <- append(which(df$score == 0), dim(df)[1] + 1)
for(i in 1:(length(score_0) - 1)) {
df$time[score_0[i]:(score_0[i + 1] - 1)] <-
ifelse(df$name[score_0[i]:(score_0[i + 1] - 1)] == df$name[score_0[i]],
df$time[score_0[i]],
df$time[score_0[i]:(score_0[i + 1] - 1)])
}
> df
name time score
1 x 1 0
2 x 1 4
3 x 1 3
4 x 1 5
5 x 2 0
6 x 2 1
7 y 1 5
8 y 2 0
9 y 2 5
10 y 2 8
score_0 给出df$score == 0 所在的索引。我们看到df$time[2:4] 现在都等于 1,在df$time[6:7] 中只有第一个发生了变化,因为第二个有df$name == 'y',而最接近df$score == 0 的上一行有df$name == 'x'。最后两行也已正确更改。
【问题讨论】:
-
如果
df [ 7 , "time" ]等于2会怎样?是否会更改为1,因为它是name==y的第一个条目,或者您将保持不变? -
@Masoud,您只需将其保持不变,因为
df$name与最接近df$score == 0的上一行不匹配 -
只是一个建议,当使用样本或其他随机函数时,使用
set.seed,这样每个人都会得到相同的输出。干杯,欢迎加入社区。span> -
@Masoud,感谢
set.seed()的提示和简洁的答案!