2015-02-16 26 views
21

Ho una domanda sulla funzione di riduzione in R. Ho letto la sua documentazione, ma sono ancora un po 'confuso. Quindi, ho 5 vettori con il nome dei geni. Ad esempio:Comprendere la funzione `Reduce`

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

E mi piacerebbe scoprire quali geni sono presenti in almeno due vettori. Alcune persone hanno suggerito:

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

Io apprezzo molto se qualcuno potesse spiegare a me come funziona questa affermazione, perché ho visto Ridurre utilizzato in altri scenari. Grazie!

+3

La tua domanda è davvero " Come posso trovare quali geni/elementi sono presenti in almeno due vettori? " Se così fosse, 'Reduce()' non * sarà * utile, anche se renderebbe facile rispondere alla domanda "quali geni sono presenti in ** tutti ** dei vettori?" –

risposta

23

Reduce accetta una funzione binaria e un elenco di elementi di dati e successivamente applica la funzione agli elementi dell'elenco in modo ricorsivo. Per esempio:

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

è lo stesso di

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

Tuttavia, non credo che il costrutto vi aiuterà a qui come restituirà solo quegli elementi che sono comuni a tutti i vettori.

per contare il numero di vettori che un gene appare in voi potrebbe effettuare le seguenti operazioni:

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 
+0

Grazie mille per il vostro contributo. Non ho mai usato le funzioni di tabella e addmargins prima. Se non ti dispiace, vorrei chiederti di loro. Tabella – Johnathan

+0

: così il gene è l'oggetto che può essere utilizzato come fattore (cioè i dati categoriali) e vec è il nome delle dimensioni (ad esempio "v1", "v2"), giusto? Sono confuso su cosa significhi il tempo.Restituisce vettori di lunghezza. Per quanto riguarda gli addmargins, è una funzione che estende una tabella per aggiungere i totali marginali (cioè i conteggi totali dei casi rispetto alle categorie di interesse), giusto? "2" significa aggiungere una colonna che manterrà i totali marginali della riga, giusto? Infine, l'ultimo argomento è un elenco che contiene la funzione. Grazie per il tuo tempo e aiuto! – Johnathan

+1

@Johnathan Sì, hai ragione. 'times' è un argomento di' rep' che determina quante volte ogni elemento viene ripetuto - questo per garantire che i geni siano mappati alla variabile corretta. – James

23

Un bel modo per vedere cosa Reduce() sta facendo è di eseguirlo con il suo argomento accumulate=TRUE. Quando accumulate=TRUE, restituirà un vettore o un elenco in cui ogni elemento mostra il suo stato dopo aver elaborato il primo n elementi dell'elenco in x. Ecco un paio di esempi:

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 
+0

Può essere usato con maggiore di confronti, ovviamente l'ho provato e ho ottenuto il primo numero nella sequenza seguito da 11111 o 00000. I miei valori attesi per qualcosa come Riduci ('<', c (3,4,7, 2,6,8,9), accumulate = T) sarebbe stato 3 3 2 2 2 2. Ciò è possibile con Riduzione? Un po 'di spiegazione, ho assunto Reduce prende gli elementi di un vettore 2 alla volta partendo da sinistra. Dato che la mia funzione è "minore di" confronta i primi 2 restituendo il numero più piccolo, quindi confronta quello al 3 ° restituendo il più piccolo ... – user3507767

+0

solo per chiarire, so che posso ottenere i risultati desiderati con cummin(), solo cercando di capire Reduce() qui. – user3507767

6

Assumendo i valori di input forniti alla fine di questa risposta, l'espressione

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

dà i geni che sono presenti in tutti i vettori, non i geni che sono presente in almeno due vettori. Significa:

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

Se vogliamo che i geni che sono in almeno due vettori:

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" 

o

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

Nota: Abbiamo usato:

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