У меня есть такая таблица:
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, и это соответствует L в столбце f.
Я пробую это с помощью библиотеки Таблица данных
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.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[, 1:4], 1, function(a) any(a %in% c("0/1","1/0")) && !any(a[1:3] == "./.")) & data$f == "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[f= = "L", .SD[apply((.SD= = "1/0" | .SD= = "0/1") & !apply(.SD= = "./.",1,any), 1, any)],
.SDcols=c("a","b","c","d")]
Вот простое решение с использованием apply
из базы R -
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
Это не сработало бы так, как ожидалось, если бы, например, «0/1» в f
или «./.» в d
.
Сначала вы можете объединить столбцы a
, b
, c
и d
вместе.
data[, abcd := paste(a, b, c, d)]
Затем я бы создал еще один новый столбец, который сообщит мне, выполнены ли условия. Я сначала ставил на все FALSE
.
data[, Selection := F]
Далее только для столбцов, соответствующих условиям, назначается TRUE
.
(1) наличие "0/1"
или "1/0"
в a
, b
, c
или d
, или просто abcd
(2) отсутствие "./."
в abcd
(3) наличие "L"
в столбце f
data[(grepl("0/1", abcd) | grepl("1/0", abcd)) & !grepl("\\./\\.", abcd) &
f == "L",
Selection := T]
Отсюда я могу выбрать строки, необходимые для
data[(Selection), ]
Если один из ответов касается вашего вопроса, пожалуйста, принять это; это не только дает некоторую льготу отвечающему на некоторые вопросы, но также дает некоторое завершение для читателей, задающих аналогичные вопросы. Хотя вы можете принять только один ответ, у вас есть возможность проголосовать столько, сколько вы считаете полезными. (Если по-прежнему возникают проблемы, вам, вероятно, придется отредактировать свой вопрос, указав более подробную информацию.)