Tengo una matriz binaria delimitada de la pestaña de los nombres y genes de las cepas bacterianas, que se enumeran como presentes (1) o ausentes (0), que se emite por Roary (Paseoducto del pangeno).

Esta es una versión simulada de los datos:

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

Al lado de un lado, está estructurado así cuando lo leo en R usando 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

Hay varios miles de genes y aproximadamente 30 cepas en mi matriz.

Quiero identificar todos los genes que están ausentes (0) en un cierto subconjunto de las cepas y guardarlas como un vector (LISTA?) Para usar en un análisis adicional (por ejemplo, como término de filtro para un marco de datos similar).

Para el ejemplo anterior, solo quiero los genes que están ausentes tanto en la tensión A como en la cepa B (y, por lo tanto, están presentes en C y / o D). Así que esperaría obtener genes G3 y G4.

Habiendo hecho algunas buscando una solución, he alargado los datos usando pivot_longer para que esté estructurado como test en mi ejemplo. Intenté filtrar así:

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

Lo que le da G3 y G4 como quiero, pero también G5, que no, como está presente en el gen 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

¿Alguien puede ayudarme con los términos de filtro correctos?

3
Mark 8 jun. 2021 a las 22:49

3 respuestas

La mejor respuesta

Podemos hacer un grupo por operación, es decir, agrupados por 'gen', verifique si all El 'A', 'B' se encuentra en la 'cepa' donde el valor 'pres_abs' es 0 y para evitar que la 1 Los valores en Pres_abs, crean una segunda condición, es decir, 'pres_abs' como 0

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

Touptt

# 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

Si necesitamos los 1 valores también,

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

-salida

# 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 jun. 2021 a las 19:55

Aquí hay una manera en que suma pres_abs para las cepas que le interesa.

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

Lo anterior devuelve todas las observaciones para esas cepas. Alternativamente, podrías hacer un filtro de dos pasos:

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 jun. 2021 a las 19:57

No te molestes en hacer los datos de largo. Lo cambié de vuelta a ancho y filtré desde allí.

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"

EDITAR: Mostrar any_of con todo el ejemplo de trabajo

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 jun. 2021 a las 20:57