web-dev-qa-db-fra.com

Comprendre la fonction `Réduire`

J'ai une question sur la fonction Réduire dans R. J'ai lu sa documentation, mais je suis encore un peu confus. Donc, j'ai 5 vecteurs avec le nom des gènes. Par exemple:

v1 <- c("geneA","geneB",""...)
v2 <- c("geneA","geneC",""...)
v3 <- c("geneD","geneE",""...)
v4 <- c("geneA","geneE",""...)
v5 <- c("geneB","geneC",""...)

Et je voudrais savoir quels gènes sont présents dans au moins deux vecteurs. Certaines personnes ont suggéré:

Reduce(intersect,list(a,b,c,d,e))

J'apprécierais grandement si quelqu'un pouvait s'il vous plaît m'expliquer comment fonctionne cette déclaration, car j'ai vu réduire utilisé dans d'autres scénarios.

31
Johnathan

Reduce prend une fonction binaire et une liste d'éléments de données et applique successivement la fonction aux éléments de la liste de manière récursive. Par exemple:

Reduce(intersect,list(a,b,c))

est le même que

intersect((intersect(a,b),c)

Cependant, je ne pense pas que cette construction vous aidera ici car elle ne renverra que les éléments communs aux vecteurs tous.

Pour compter le nombre de vecteurs dans lesquels un gène apparaît, vous pouvez procéder comme suit:

vlist <- list(v1,v2,v3,v4,v5)
addmargins(table(gene=unlist(vlist), vec=rep(paste0("v",1:5),times=sapply(vlist,length))),2,list(Count=function(x) sum(x[x>0])))
       vec
gene    v1 v2 v3 v4 v5 Count
  geneA  1  1  0  1  0     3
  geneB  1  0  0  0  1     2
  geneC  0  1  0  0  1     2
  geneD  0  0  1  0  0     1
  geneE  0  0  1  1  0     2
33
James

Une belle façon de voir ce que fait Reduce() est de l'exécuter avec son argument accumulate=TRUE. Quand accumulate=TRUE, il retournera un vecteur ou une liste dans laquelle chaque élément montre son état après avoir traité les premiers n éléments de la liste dans x. Voici quelques exemples:

Reduce(`*`, x=list(5,4,3,2), accumulate=TRUE)
# [1]   5  20  60 120

i2 <- seq(0,100,by=2)
i3 <- seq(0,100,by=3)
i5 <- seq(0,100,by=5)
Reduce(intersect, x=list(i2,i3,i5), accumulate=TRUE)
# [[1]]
#  [1]   0   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30  32  34  36
# [20]  38  40  42  44  46  48  50  52  54  56  58  60  62  64  66  68  70  72  74
# [39]  76  78  80  82  84  86  88  90  92  94  96  98 100
# 
# [[2]]
#  [1]  0  6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96
# 
# [[3]]
# [1]  0 30 60 90
27
Josh O'Brien

En supposant les valeurs d'entrée données à la fin de cette réponse, l'expression

Reduce(intersect,list(a,b,c,d,e))
## character(0)

donne les gènes qui sont présents dans tous les vecteurs, pas les gènes qui sont présents dans au moins deux vecteurs. Ça veut dire:

intersect(intersect(intersect(intersect(a, b), c), d), e)
## character(0)

Si nous voulons les gènes qui sont dans au moins deux vecteurs:

L <- list(a, b, c, d, e)
u <- unlist(lapply(L, unique)) # or:  Reduce(c, lapply(L, unique))

tab <- table(u)
names(tab[tab > 1])
## [1] "geneA" "geneB" "geneC" "geneE"

ou

sort(unique(u[duplicated(u)]))
## [1] "geneA" "geneB" "geneC" "geneE"

Remarque: Nous avons utilisé:

a <- c("geneA","geneB")
b <- c("geneA","geneC")
c <- c("geneD","geneE")
d <- c("geneA","geneE")
e <- c("geneB","geneC")
7
G. Grothendieck