我有以下数据框
id<-c(1,1,1,1,2,2,2,2,3,3,3,3)
time<-c(0,1,2,3,0,1,2,3,0,1,2,3)
value<-c(1,1,6,1,2,6,2,2,1,1,6,1)
d<-data.frame(id, time, value)
每个ID只显示一次值6。对于每个id,我想删除时间大于值6的时间的所有行
我希望最终的数据框能够显示所有ID的所有观察结果,而不是“6”。对于具有“6”观察值的那些ID,我希望所有观察到的时间&lt;那次观察的时间。
我搜索了SO,关于条件行删除有几个问题(和答案),但我发现没有什么接近我需要的。
在上述情况下,最终数据框应为
id time value
1 1 0 1
2 1 1 1
3 1 2 6
5 2 0 2
6 2 1 6
9 3 0 1
10 3 1 1
11 3 2 6
非常感谢。
答案 0 :(得分:1)
为每个ID选择值6的时间:
mt <- d[d$value == 6, c("id","time")]
names(mt) <- c("id", "max.time")
合并d和mt以获得每个id的最大时间:
d <- merge(d,mt)
子集和清理:
d <- subset(d, time <= max.time)
d$max.time <- NULL
答案 1 :(得分:1)
这是使用plyr
:
library(plyr)
ddply(d, "id", function(x) subset(x, time <= x[x$value == 6, "time"]))
id time value
1 1 0 1
2 1 1 1
3 1 2 6
4 2 0 2
5 2 1 6
6 3 0 1
7 3 1 1
8 3 2 6
更新以解释说明中的评论
样本数据集以匹配以下描述:
id<-c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4)
time<-c(0,1,2,3,0,1,2,3,0,1,2,3,3,2,1)
value<-c(1,1,6,1,2,6,2,2,1,1,6,1,1,2,3)
d<-data.frame(id, time, value)
在匿名函数中添加一些额外的检查:
ddply(d, "id",
function(x) {
if (any(x$value == 6)) {
subset(x, time <= x[x$value == 6, "time"])
} else {
x
}
}
)
检查结果
id time value
1 1 0 1
2 1 1 1
3 1 2 6
4 2 0 2
5 2 1 6
6 3 0 1
7 3 1 1
8 3 2 6
9 4 3 1
10 4 2 2
11 4 1 3
答案 2 :(得分:0)
我不确定我是否理解您的选择方法6.如果用户已定义,则以下内容将为您提供所选行:
x <- max(d[d$value==6, 'time']) #find the max time associate with value =6
subset(d, time<=x) #subset and select only time less than or = to 6
如果您希望自动化6的值,并且正在寻找所有ID的最大价值份额,那么我在这里做了一个令人费解的方式。任何时候你看到unlist通常我知道sapply将是一个betetr选择,可能是一个完整的其他方法,但不知道如何选择6这是我现在提出的:
y <- with(d, by(value, id, FUN=rle))
z <- lapply(seq_along(y), function(x) unlist(y[[x]][1])==1)
j <- lapply(seq_along(y), function(x) unlist(y[[x]][2])[z[[x]]])
mv <- max(as.numeric(as.character(unlist(subset(data.frame(table(unlist(j))),
Freq==length(j))['Var1']))))
x <- max(d[d$value==mv, 'time'])
subset(d, time<=x)