在数据框中,我想替换超过给定阈值的系列中的值。
例如,在'time'指定的系列中的一个组('ID')中,如果'value'超过3,我想使所有以下条目也等于3.
ID <- as.factor(c(rep("A", 3), rep("B",3), rep("C",3)))
time <- rep(1:3, 3)
value <- c(c(1,1,2), c(2,3,2), c(3,3,2))
dat <- cbind.data.frame(ID, time, value)
dat
ID time value
A 1 1
A 2 1
A 3 2
B 1 2
B 2 3
B 3 2
C 1 3
C 2 3
C 3 2
我希望它是:
ID time value
A 1 1
A 2 1
A 3 2
B 1 2
B 2 3
B 3 3
C 1 3
C 2 3
C 3 3
这应该很容易,但我无法弄清楚。谢谢!
答案 0 :(得分:4)
ave
函数允许您将函数应用于每个分组,从而使这变得非常简单。在这种情况下,我们将调整cummax
(累计最大值)以查看我们是否已经看到了3。
dat$value2<-with(dat, ave(value, ID, FUN=
function(x) ifelse(cummax(x)>=3, 3, x)))
dat;
# ID time value value2
# 1 A 1 1 1
# 2 A 2 1 1
# 3 A 3 2 2
# 4 B 1 2 2
# 5 B 2 3 3
# 6 B 3 2 3
# 7 C 1 3 3
# 8 C 2 3 3
# 9 C 3 2 3
如果您想要永不减少的值,也可以使用FUN=cummax
。如果您想保持不变,我不确定序列c(1,2,1)
。
答案 1 :(得分:1)
如果您可以假设您的数据按组排序,那么这应该很快,基本上依赖于幕后的findInterval():
library(IRanges)
id <- Rle(ID)
three <- which(value>=3L)
ir <- reduce(IRanges(three, end(id)[findRun(three, id)])))
dat$value[as.integer(ir)] <- 3L
这可以避免循环群组。