R:如何复制一列,如果原件在第 x 行中为 "TRUE",则副本将在第 x-250 行到第 x+250 行中为 "TRUE"?

R: How to copy a column such that if the original was "TRUE" in row x, the copy will be "TRUE" in rows x-250 through to x+250?

希望这个问题提得清楚!我看过很多关于循环和 if_else 子句等的指南,但还没有弄明白。

我正在尝试在大量 txt 文件中查找出现多个(比如 5 个)关键字的段落。示例关键字是“motion”和“cause”。 我的数据很整洁(txt 文件已拆分,因此每行有一个单词)并使用正则表达式添加了列(每个关键字一个),如果该行包含关键字,则显示“TRUE”,否则为 false . 现在,为了找到感兴趣的段落,我想复制同一行中显示“TRUE”的每一列,以及这些行上方和下方的 250 行。因此,例如,当该行包含单词“motion”时,我想复制显示“TRUE”的列,这样在新列中,单词“motion”周围的 500 个单词也是“TRUE”(即上面的 250 行在单词所在的下方)。 我的想法是,然后我可以轻松地检查是否有任何行的所有复制列都为真,这表明有一个 500 字的段落出现了我的所有关键字。

我尝试以各种方式学习和使用循环来制作这些复制的列,但到目前为止我还没有取得任何成功。这是我最近一次尝试的样子,但它似乎只是将相同的行指定为“TRUE”250 次,而不是将接下来的 250 行设为“TRUE”。 (它还给出了错误消息“'mutate()' 输入 'copied_column' 的问题。我输入 'copied_column' 的下标越界是 'case_when(...)'。”)

n <-1
corpus <- corpus #>#
    mutate(copied_column = case_when(
      str_detect(original_column, "TRUE") ~ (repeat{
        n <- n+1
        str_detect(orginal_column, "FALSE")
        if (n == 250) {
          break
        }
       })
    ))

如果有人有任何建议,我们将非常欢迎。如果您知道我可能应该使用的任何功能,或者如果您知道如何正确使用上面示例中的功能,那将对我有很大帮助。

也许下面的功能可以解决问题。用假数据测试。

segmentTRUE <- function(X, y, dist){
  f <- function(y, n, d){
    from <- max(1, y - d)
    to <- min(n, y + d)
    from:to
  }
  y <- deparse(substitute(y))
  w <- which(X[[y]])
  i <- Reduce(union, mapply(f, w, MoreArgs = list(n = nrow(X), d = dist)))
  X[i, y] <- TRUE
  X[[y]]
}

测试

以 3 种不同的方式组成一些数据和 运行 函数,其中两种在 magrittr 管道中。

x <- rep(FALSE, 5e1)
x[c(2, 10, 35, 47)] <- TRUE
df1 <- data.frame(words = rep(letters, length.out = 5e1), x)
head(df1)
d <- 5

segmentTRUE(df1, x, d)
df1 %>% segmentTRUE(x, d)
df1 %>% mutate(x = segmentTRUE(., x, d))

编辑

使用 nrow(df1) == 1e4,以下函数比 Reduce 版本快几个数量级。

segmentTRUE2 <- function(X, y, dist){
  f <- function(y, n, d){
    max(1, y - d):min(n, y + d)
  }
  y <- deparse(substitute(y))
  w <- which(X[[y]])
  i <- unique(unlist(mapply(f, w, MoreArgs = list(n = nrow(X), d = dist))))
  X[i, y] <- TRUE
  X[[y]]
}

identical(segmentTRUE(df1, x, d), segmentTRUE2(df1, x, d))
#[1] TRUE