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



我有一个这样的表:

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[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

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

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

这为我们提供了前四列中具有两个"所需"模式之一的实例。我们想要任何列都有它的行,所以我们在它们之间"任意":

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"(中,直接将它们与&逻辑链接。

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

另一个选项:

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

类似于前面的答案:

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

下面是一个使用基于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

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

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

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

data[, Selection := F]

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

(1( 在abcd中具有"0/1""1/0",或仅具有abcd

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

(3( 在f列中具有"L"

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

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

data[(Selection), ]

最新更新