如果满足条件,请替换列的后续值

时间:2019-01-09 18:05:35

标签: r

我有一个数据框,如果满足条件,我想在其中替换列的值,直到达到一定数量的行

示例数据框

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中没有循环吗?

2 个答案:

答案 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指出了这一点。)