Выберите строки, где хотя бы условие присутствует в 2 столбцах в R

У меня есть большой набор данных с одним столбцом имен генов и четырьмя столбцами методов обнаружения (в данном случае я назвал их X1, X2, X3 и X4). Я хотел бы выбрать строки, где гены выбраны по крайней мере 2 методом обнаружения. Пример таблицы:

Table:
Row   Gene   X1   X2   X3   X4  
 1      A     1    0    0    0
 2      A     0    0    1    0
 3      A     0    1    0    0
 4      B     0    0    1    0
 5      B     0    0    1    0
 6      C     0    0    0    1
 7      D     0    0    1    0
 8      D     0    1    0    0
 9      D     0    1    0    0
 10     E     0    0    1    0
 11     E     0    0    1    0

Таким образом, я хочу выбрать строки 1,2,3 (методы X1, X2 и X3 обнаружили ген A) и строки 7,8,9, где методы X2 и X3 обнаружили ген D.

Спасибо за вашу помощь.


r
person Eduardo Herreros    schedule 01.12.2020    source источник
comment
Не могли бы вы поделиться кодом того, что вы уже пробовали? Как правило, вы можете просто вычислить сумму X1:X4 для каждого гена, а затем отфильтровать строки/гены, где сумма = 2.   -  person deschen    schedule 01.12.2020
comment
Альтернативой может быть просто подсчет столбца Gene, поскольку кажется, что ген появляется столько раз, сколько он был обнаружен, т. е. ген A обнаруживается 3 раза, а ген C обнаруживается только один раз.   -  person deschen    schedule 01.12.2020
comment
Обратите внимание, что в примере OP гены, которые должны давать положительное совпадение, — это A и D, все строки которых в сумме дают 1, а не 2.   -  person Jason    schedule 01.12.2020


Ответы (2)


Чтобы показать, какие гены были обнаружены двумя или более методами, это сработает.

Укороченная версия:

если zz - это ваш data.frame, то:

yy <- by(zz, zz$Gene, function(dat) {sum(apply(dat[,-c(1,2)], 2, any)) >= 2} )
zz[zz$Gene %in% which(yy),]

Длинная версия

# load the data:
zz <- read.table(header = TRUE, text = "
Row Gene X1 X2 X3 X4 
1 A 1 0 0 0
2 A 0 0 1 0
3 A 0 1 0 0
4 B 0 0 1 0
5 B 0 0 1 0
6 C 0 0 0 1
7 D 0 0 1 0
8 D 0 1 0 0
9 D 0 1 0 0
10 E 0 0 1 0
11 E 0 0 1 0")

# now check, gene by gene, whether at least two columns have at least one 1.
# note that the repeated any() statements can be replaced by a loop or  
# apply(), but for only four columns this works, is easy enough to type, 
# and much easier to understand
yy <- by(zz, zz$Gene, function(dat) {(any(dat$X1) + 
                                      any(dat$X2) + 
                                      any(dat$X3) + 
                                      any(dat$X4) ) >= 2} )

# or, the apply way, in case there are a lot of columns.
# "-c(1,2)" as a column index means "every column except the first two",
# so if the data has 3, 4, or 30 methods, this code stays the same.
yy <- by(zz, zz$Gene, function(dat) {sum(apply(dat[,-c(1,2)], 2, any)) >= 2} )

yy
zz$Gene: A
[1] TRUE
--------------------------------------------------------------------------- 
zz$Gene: B
[1] FALSE
--------------------------------------------------------------------------- 
zz$Gene: C
[1] FALSE
--------------------------------------------------------------------------- 
zz$Gene: D
[1] TRUE
--------------------------------------------------------------------------- 
zz$Gene: E
[1] FALSE

Теперь нужно найти строки, соответствующие генам, которые получили TRUE результатов.

Найдите имена zz (A, B, C,...), которые соответствуют yy значениям TRUE, и проиндексируйте data.frame на основе этого...

which(yy)  # equivalent to which(yy == TRUE)

дает

A D 
1 4 

а также

names(which(yy))

дает

[1] "A" "D"

so...

zz[zz$Gene %in% names(which(yy)),]

дает

  Row Gene X1 X2 X3 X4
1   1    A  1  0  0  0
2   2    A  0  0  1  0
3   3    A  0  1  0  0
7   7    D  0  0  1  0
8   8    D  0  1  0  0
9   9    D  0  1  0  0
person Jason    schedule 01.12.2020
comment
Спасибо Джейсон! он работает отлично, я просто меняю == на% в%, потому что я получал это предупреждение, что более длинная длина объекта не кратна более короткой длине объекта, исправленной% в% - person Eduardo Herreros; 01.12.2020
comment
Упс. Ошибка копирования и вставки времени. Спасибо за улов. - person Jason; 01.12.2020

Вы можете использовать rowsum и rowSums, чтобы найти те, у которых более 1 метода, и %in%, чтобы найти совпадающие строки.

x <- rowSums(rowsum(zz[3:6], zz[,2]) > 0) > 1
zz$Row[zz$Gene %in% names(x[x])]
#[1] 1 2 3 7 8 9
person GKi    schedule 01.12.2020