我有一个数据框,如果满足条件,我想在其中替换列的值,直到达到一定数量的行
示例数据框
A B C
10 15 0
11 11 6
3 12 0
4 6 9
5 9 0
7 8 0
7 1 8
如果C中任何行的值都大于0,则需要用0替换C的下5个值,从而产生以下数据帧
A B C
10 15 0
11 11 6
3 12 0
4 6 0
5 9 0
7 8 0
7 1 0
有什么方法可以在R中没有循环吗?
答案 0 :(得分:5)
首先,检查which(df$C > 0)
。对于结果中的每个元素,使用1:5
添加lapply
。然后,用unique
删除结果中的所有重复项(unlist
之后)。最后,确保没有任何行大于nrow(df)
和pmin
,并为这些行设置df$C
等于0
。
df$C[pmin(nrow(df), unique(unlist(lapply(which(df$C > 0), `+`, 1:5))))] <- 0
由于您最初标记了dplyr
,所以这是一个tidyverse方法(除非您将结果分配给df
,否则请不要修改df
)
library(tidyverse)
inds <-
which(df$C > 0) %>%
map(~ . + 1:5) %>%
unlist %>%
unique %>%
pmin(nrow(df))
df %>%
mutate(C = replace(C, inds, 0))
edit:实际上看来unique
步骤是不必要的。不知道保留重复索引是否会对性能产生影响,或者与使用unique
答案 1 :(得分:3)
这是一个“滚动窗口”操作,因此我建议使用zoo::rollapply
。
dat <- read.table(header=TRUE, text='
A B C
10 15 0
11 11 6
3 12 0
4 6 9
5 9 0
7 8 0
7 1 8')
zoo::rollapply(dat$C, 5+1, FUN=function(a) {
l <- length(a)
if (any(a[-l] != 0)) 0 else a[l]
}, fill = NA, align = "right", partial = TRUE)
# [1] 0 6 0 0 0 0 0
(我用5+1
来表示我们需要多于要清空的行,如查看a[-l]
所示。非常感谢@IceCreamToucan指出了这一点。)>