根据匹配列和不匹配列的组合选择行

时间:2018-10-30 23:54:36

标签: r data.table subset

我有一张这样的桌子:

 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

你知道我该怎么做到吗?

6 个答案:

答案 0 :(得分:2)

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 中有行,因此我们对它们进行“ 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”,直接将它们与&进行逻辑链接。

答案 1 :(得分:1)

这绝不比工作的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函数对数据逐行应用一个函数。

答案 2 :(得分:1)

类似于上一个答案:

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

答案 3 :(得分:1)

另一个选择:

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

答案 4 :(得分:0)

这是使用基数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

答案 5 :(得分:0)

您可以首先将列abcd串联在一起。

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

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

data[, Selection := F]

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

(1)在"0/1""1/0"abc中有dabcd }

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

(3)在"L"列中有f

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

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

data[(Selection), ]