【问题标题】:Replace subsequent values of a column if a condition is met如果满足条件,则替换列的后续值
【发布时间】:2019-01-09 18:05:34
【问题描述】:

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

示例数据框

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,则需要将 C 的下 5 个值替换为 0,从而产生以下数据帧

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 中没有循环的任何方法可以实现这一点?

【问题讨论】:

  • 真的是“仅接下来的 5 行”,还是“所有行都在后面”?
  • 接下来的 5 行。在示例中意外地两者都是正确的。
  • NinjaR,如果其中一个答案解决了您的问题,请accept it;这样做不仅为回答者提供了一些积分,而且还为有类似问题的读者提供了一些关闭。尽管您只能接受一个答案,但您可以选择对您认为有帮助的人进行投票。 (如果仍有问题,您可能需要编辑您的问题并提供更多详细信息。)

标签: r


【解决方案1】:

首先,检查which(df$C > 0)。对于结果中的每个元素,使用lapply 添加1:5。然后,使用unique(在unlisting 之后)删除结果中的所有重复项。最后,确保没有行大于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))

编辑:实际上似乎unique 步骤是不必要的。不确定保留重复索引是否会对性能产生任何影响,或者如果有,与使用unique相比如何@

【讨论】:

  • 我喜欢使用数组,顺便说一句...除了 window-ops 之外,array-ops 还可以轻松处理这个问题...而且速度可能更快。
【解决方案2】:

这是一个“滚动窗口”操作,所以我建议使用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 指出这一点。)

【讨论】:

  • 我认为如果这只是做 4 行而不是 5 行,那么 8 会被保留为 8。
  • 巴津加。不错的收获,@IceCreamToucan。
猜你喜欢
  • 1970-01-01
  • 2013-11-15
  • 2020-08-18
  • 1970-01-01
  • 2018-10-23
  • 2018-08-24
  • 2021-12-22
  • 2020-05-16
相关资源
最近更新 更多