У меня есть разделенная табуляцией двоичная матрица названий и генов бактериальных штаммов, перечисленных как присутствующие (1) или отсутствующие (0), которые выводятся ROARY (конвейер пангенома).

Это фиктивная версия данных:

strain <- rep(letters[1:4], 5)
gene <- c(rep("G1", 4), rep("G2", 4), rep("G3", 4), rep("G4", 4), rep("G5", 4))
pres_abs <- c(1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1) 
test <- tibble(strain, gene, pres_abs)

   strain gene  pres_abs
   <chr>  <chr>    <dbl>
 1 a      G1           1
 2 b      G1           1
 3 c      G1           1
 4 d      G1           1
 5 a      G2           1
 6 b      G2           1
 7 c      G2           0
 8 d      G2           0
 9 a      G3           0
10 b      G3           0
11 c      G3           1
12 d      G3           1
13 a      G4           0
14 b      G4           0
15 c      G4           0
16 d      G4           1
17 a      G5           1
18 b      G5           0
19 c      G5           1
20 d      G5           1

Кстати, когда я читал его в R с помощью read_tsv(), он имеет такую ​​структуру:

  gene      a     b     c     d
  <chr> <dbl> <dbl> <dbl> <dbl>
1 G1        1     1     1     1
2 G2        1     1     0     0
3 G3        0     0     1     1
4 G4        0     0     0     1
5 G5        1     0     1     1

В моей матрице несколько тысяч генов и около 30 штаммов.

Я хочу идентифицировать все гены, которые отсутствуют (0) в определенном подмножестве штаммов, и сохранить их как вектор (список?) Для использования в дальнейшем анализе (например, как термин фильтра для аналогичного фрейма данных).

В приведенном выше примере мне нужны только гены, которые отсутствуют как в штамме a, так и в штамме b (и, следовательно, присутствуют в штамме c и / или d). Так что я ожидал получить гены G3 и G4.

Проделав поиск решения, я увеличил данные с помощью pivot_longer, чтобы они были структурированы как test в моем примере. Я пробовал фильтровать вот так:

test %>% filter(strain %in% c("a", "b") & pres_abs == 0)

Это дает G3 и G4, как я хочу, но также и G5, которого у меня нет, поскольку он присутствует в гене a.

  strain gene  pres_abs
  <chr>  <chr>    <dbl>
1 a      G3           0
2 b      G3           0
3 a      G4           0
4 b      G4           0
5 b      G5           0

Может ли кто-нибудь помочь мне с правильными условиями фильтрации?

3
Mark 8 Июн 2021 в 22:49

3 ответа

Лучший ответ

Мы можем создать группу по операции, то есть сгруппировать по «гену», проверить, all найдены ли «a», «b» в «штамме», где значение «pres_abs» равно 0, и чтобы не получить 1 значения в pres_abs, создайте второе условие, например, "pres_abs" как 0

library(dplyr)
test %>%
     group_by(gene) %>% 
     filter(all(c("a", "b") %in% strain[pres_abs == 0]),
               pres_abs == 0) %>%
     ungroup

-выход

# A tibble: 5 x 3
  strain gene  pres_abs
  <chr>  <chr>    <dbl>
1 a      G3           0
2 b      G3           0
3 a      G4           0
4 b      G4           0
5 c      G4           0

Если нам также нужны значения 1,

test %>%
     group_by(gene) %>% 
     filter(all(c("a", "b") %in% strain[pres_abs == 0])) %>%
     ungroup

-вывод

# A tibble: 8 x 3
  strain gene  pres_abs
  <chr>  <chr>    <dbl>
1 a      G3           0
2 b      G3           0
3 c      G3           1
4 d      G3           1
5 a      G4           0
6 b      G4           0
7 c      G4           0
8 d      G4           1
2
akrun 8 Июн 2021 в 19:55

Вот способ суммирования pres_abs интересующих вас штаммов.

test %>%
  group_by(gene) %>%
  filter(sum(pres_abs[strain %in% c("a", "b")]) == 0)
# # A tibble: 8 x 3
# # Groups:   gene [2]
#   strain gene  pres_abs
#   <chr>  <chr>    <dbl>
# 1 a      G3           0
# 2 b      G3           0
# 3 c      G3           1
# 4 d      G3           1
# 5 a      G4           0
# 6 b      G4           0
# 7 c      G4           0
# 8 d      G4           1

Приведенное выше возвращает все наблюдения для этих штаммов. В качестве альтернативы вы можете использовать двухэтапный фильтр:

test %>%
  group_by(gene) %>%
  filter(strain %in% c("a", "b")) %>%
  filter(sum(pres_abs) == 0)
# # A tibble: 4 x 3
# # Groups:   gene [2]
#   strain gene  pres_abs
#   <chr>  <chr>    <dbl>
# 1 a      G3           0
# 2 b      G3           0
# 3 a      G4           0
# 4 b      G4           0
3
Gregor Thomas 8 Июн 2021 в 19:57

Не беспокойтесь о том, чтобы данные были длинными. Я изменил его обратно на широкий и отфильтровал оттуда.

test %>% 
  pivot_wider(gene, names_from = strain, values_from = pres_abs, values_fill = 0) %>% 
  filter(across(c(a,b), ~ .==0)) %>% 
  pull(gene)
[1] "G3" "G4"

РЕДАКТИРОВАТЬ: показать any_of с рабочим примером

test %>% 
  pivot_wider(gene, names_from = strain, values_from = pres_abs, values_fill = 0) %>% 
  filter(across(any_of(c("a","b","z","q","t")), ~ .==0)) %>% 
  pull(gene)
[1] "G3" "G4"

2
zimia 8 Июн 2021 в 20:57