【问题标题】:R add new column depending on values in a range in different columnsR根据不同列中范围内的值添加新列
【发布时间】:2018-06-17 19:25:02
【问题描述】:

我有一个带有两个布尔列 A 和 B 的 data.table。我想添加一个取决于 A 和 B 的新布尔行 C,但我在“查找”前一行和上一行时遇到了麻烦。

我想如下定义 C。如果有一行 A=1 并且在周围三行的范围内至少有一个 B=1,那么我希望 C 在 A=1 和所有其他行上 C=0 的行上变为 C=1在范围内。否则 C 应该是 C=B。

如果两个范围重叠并且都包含 B=1,则 C 应该在 A=1 和 C=0 的两行上都变为 C=1。如需更多说明:

df <- data.table(A=c(0,0,0,1,0,0,0,0,0,0,0,1,1,0,0), 
                 B=c(0,1,0,0,0,1,0,1,1,0,0,0,0,0,1))

    A B                                        A B C
1:  0 0 #                                  1:  0 0 0
2:  0 1 #                                  2:  0 1 0
3:  0 0 #                                  3:  0 0 0
4:  1 0 # range of three                   4:  1 0 1
5:  0 0 #                                  5:  0 0 0
6:  0 1 #                                  6:  0 1 0
7:  0 0 #                                  7:  0 0 0
8:  0 1                                    8:  0 1 1 # C = B
9:  0 1 #                                  9:  0 1 0
10: 0 0 ##                                 10: 0 0 0
11: 0 0 ##                                 11: 0 0 0
12: 1 0 ## overlapping range of three      12: 1 0 1
13: 1 0 ##                                 13: 1 0 1
14: 0 0 ##                                 14: 0 0 0
15: 0 1 ##                                 15: 0 1 0

我该怎么做,我对此一无所知。

【问题讨论】:

  • 第 4 行怎么会得到C = 1?没有“周围三行范围内至少有一个B=1”,所有B都为零。
  • 至于第 2、6、9 行,C = B 也不应该等于1 吗? (不仅仅是第 8 行。)
  • 所以感兴趣的窗口是 (row - 3 : row + 3)?
  • 您的df 与显示的df 不匹配
  • @Ryan 现在可以了,我已经更正了。

标签: r data.table


【解决方案1】:
# Find ranges where A == 1
ind <- lapply(which(df$A == 1)
              , function(i){s <- i + -3:3; s[s %in% seq(nrow(df))]})
# Remove ranges with no B == 1
good <- sapply(ind, function(i) df[i, any(B == 1)])
ind  <- unique(unlist(ind[good]))
# Assign C as described
df[, C := B]
df[ind, C := as.numeric(A == 1)]
df
#     A B C
#  1: 0 0 0
#  2: 0 1 0
#  3: 0 0 0
#  4: 1 0 1
#  5: 0 0 0
#  6: 0 1 0
#  7: 0 0 0
#  8: 0 1 1
#  9: 0 1 0
# 10: 0 0 0
# 11: 0 0 0
# 12: 1 0 1
# 13: 1 0 1
# 14: 0 0 0
# 15: 0 1 0

下面使用的数据。我更改了您的 df 定义以匹配显示的 df

df <- data.table(A=c(0,0,0,1,0,0,0,0,0,0,0,0,1,0,0), 
                 B=c(0,1,0,0,0,1,0,1,1,0,0,0,0,0,0))

df[12, A := 1]
df[15, B := 1]

df

#     A B
#  1: 0 0
#  2: 0 1
#  3: 0 0
#  4: 1 0
#  5: 0 0
#  6: 0 1
#  7: 0 0
#  8: 0 1
#  9: 0 1
# 10: 0 0
# 11: 0 0
# 12: 1 0
# 13: 1 0
# 14: 0 0
# 15: 0 1

【讨论】:

    【解决方案2】:

    这是一个基于 tidyverse 套件的解决方案:

    我定义了 2 个临时变量 - A1 确定 A = 1 是否在 (row -3 : row + 3) 窗口中的任何位置。 C1 测试 A = 1B = 1 是否在窗口的任何位置。

    library(tidyverse)
    df %>% 
      mutate(
        A1 = (cumsum(lead(A, 3, default = 0)) - cumsum(dplyr::lag(A, 4, default = 0)) > 0),
        C1 = (A & dplyr::lead(cumsum(B), n = 3, default = 0) - dplyr::lag(cumsum(B), n = 4, default = 0)) * 1,
        C = ifelse(!A1, B, C1)
      ) %>%
      select(-A1, -C1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      • 2022-11-21
      相关资源
      最近更新 更多