替换超过阈值的系列中的值

时间:2014-05-30 06:44:02

标签: r

在数据框中,我想替换超过给定阈值的系列中的值。

例如,在'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

这应该很容易,但我无法弄清楚。谢谢!

2 个答案:

答案 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

这可以避免循环群组。