【问题标题】:Select rows based on a combination of matched and not matched columns根据匹配列和不匹配列的组合选择行
【发布时间】:2018-10-30 23:54:36
【问题描述】:

我有一张这样的桌子:

 data <- data.frame(a = c("0/0", "0/1", "0/0", "0/0" ),
                    b = c("0/1", "./.", "0/1", "0/0"),
                    c = c("1/0", "0/0", "1/1", "0/0"),
                    d = c("1/0", "0/0", "1/1", "0/0"),                       
                    f = c("L", "L", "T", "L"))

我想选择包含至少一个 0/​​1 或 1/0 且没有 ./ 的任何行。在 a、b 和 c 列中,并且与 f 列中的 L 匹配。

我正在尝试使用库 data.table

data[data$a %like% "0/1|1/0" | data$b %like% "0/1|1/0"| data$c %like% "0/1|1/0" & !(data$a %like% "./.") & !(data$b %like% "./.") & !(data$c %like% "./.") & data$f == "L", ]

但它不起作用。

表格如下所示:

       a   b   c   d   f
    1 0/0 0/1 1/0 1/0  L
    2 0/1 ./. 0/0 0/0  L
    3 0/0 0/1 1/1 1/1  T
    4 0/0 0/0 0/0 0/0  L

所需的输出应如下所示:

       a   b   c   d   f
    1 0/0 0/1 1/0 1/0  L

你知道我是怎么做到的吗?

【问题讨论】:

  • 如果其中一个答案解决了您的问题,请accept it;这样做不仅为回答者提供了一些积分,而且还为有类似问题的读者提供了一些关闭。尽管您只能接受一个答案,但您可以选择对您认为有帮助的人进行投票。 (如果仍有问题,您可能需要编辑您的问题并提供更多详细信息。)

标签: r data.table subset


【解决方案1】:
data[ apply(sapply(data[1:4], `%in%`, c('0/1','1/0')), 1, any) &
      apply(sapply(data[1:3], Negate(`%in%`), c('./.')), 1, all) &
      data$f == "L", ]
#     a   b   c   d f
# 1 0/0 0/1 1/0 1/0 L

分解:

sapply(data[1:4], `%in%`, c('0/1','1/0'))
#          a     b     c     d
# [1,] FALSE  TRUE  TRUE  TRUE
# [2,]  TRUE FALSE FALSE FALSE
# [3,] FALSE  TRUE FALSE FALSE
# [4,] FALSE FALSE FALSE FALSE

这为我们提供了前四列中具有两种“想要”模式之一的实例。我们想要 any 列有它的行,所以我们在它们之间“任意”:

apply(sapply(data[1:4], `%in%`, c('0/1','1/0')), 1, any)
# [1]  TRUE  TRUE  TRUE FALSE

同样,找到那些“不想要”的模式:

sapply(data[1:3], Negate(`%in%`), c('./.'))
#         a     b    c
# [1,] TRUE  TRUE TRUE
# [2,] TRUE FALSE TRUE
# [3,] TRUE  TRUE TRUE
# [4,] TRUE  TRUE TRUE
apply(sapply(data[1:3], Negate(`%in%`), c('./.')), 1, all) # notice "all", not "any"
# [1]  TRUE FALSE  TRUE  TRUE

现在我们要在最后一列 (=="L") 中添加“L”,直接将它们与 &amp; 进行逻辑链接。

【讨论】:

    【解决方案2】:

    这绝不比有效的 data.table 解决方案快,但它适用于基础 R:

    dat <- data.frame(a = c("0/0", "0/1", "0/0", "0/0" ),
                       b = c("0/1", "./.", "0/1", "0/0"),
                       c = c("1/0", "0/0", "1/1", "0/0"),
                       d = c("1/0", "0/0", "1/1", "0/0"),                       
                       f = c("L", "L", "T", "L"))
    
    dat
    f <- which(colnames(dat) == 'f')
    rows <- apply(dat, 1, function(x)  x[f] == "L" & !any("./." == x[-f]) & any("0/1" == x[-f]) | any("1/0" == x[-f]) )
    dat[rows,]
    

    它使用apply函数对数据逐行应用函数。

    【讨论】:

      【解决方案3】:

      另一种选择:

      data[f=="L", .SD[apply((.SD=="1/0" | .SD=="0/1") & !apply(.SD=="./.",1,any), 1, any)], 
          .SDcols=c("a","b","c","d")]
      

      【讨论】:

        【解决方案4】:

        与上一个答案类似:

        apply(data[, 1:4], 1, function(a) any(a %in% c("0/1","1/0")) && !any(a[1:3] == "./.")) & data$f == "L"
        

        【讨论】:

          【解决方案5】:

          这是一个使用来自 base R 的 apply 的简单解决方案 -

          test <- apply(data, 1, function(x) {
            any(x %in% c("0/1", "1/0")) & !any(x == "./.") & x["f"] == "L"
          })
          
          data[test, ]
          
          #     a   b   c   d f
          # 1 0/0 0/1 1/0 1/0 L
          

          【讨论】:

          • 如果有例如,这将无法按预期工作。 f 中的“0/1”或“./.”在d.
          【解决方案6】:

          您可以先将abcd 列连接在一起。

          data[, abcd := paste(a, b, c, d)]
          

          然后,我将创建另一个新列,它会告诉我是否满足条件。我先设置为所有FALSE

          data[, Selection := F]
          

          接下来,只为满足条件的列分配TRUE

          (1) 在abcd 或简单的abcd 中包含"0/1""1/0"

          (2) 在abcd 中没有"./."

          (3) 在f 列中有"L"

          data[(grepl("0/1", abcd) | grepl("1/0", abcd)) & !grepl("\\./\\.", abcd) &
               f == "L",
               Selection := T]
          

          从这里,我可以选择所需的行

          data[(Selection), ]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-08-17
            • 1970-01-01
            • 2022-10-16
            • 1970-01-01
            • 2018-08-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多