2014-12-01 12 views
6
df <- data.frame(
    exp=c(1,1,2,2), 
    name=c("gene1", "gene2", "gene1", "gene2"), 
    value=c(1,1,3,-1) 
    ) 

nel tentativo di ottenere customed al dplyr e reshape2 mi sono imbattuto in un modo "semplice" per selezionare le righe sulla base di una serie di condizioni. Se voglio avere quei geni (la variabile name) che hanno value sopra 0 nell'esperimento 1 (exp == 1) E allo stesso tempo value sotto 0 nell'esperimento 2; in df questo sarebbe "gene2". Certo, ci devono essere molti modi per farlo, ad es. sottoinsieme df per ciascuna serie di condizioni (exp == 1 & valore> 0, e exp == 2 e il valore < 0) e poi si uniscono i risultati di questi sottoinsieme:R ottenere righe in base a più condizioni - uso dplyr e reshape2

library(dplyr)  
inner_join(filter(df,exp == 1 & value > 0),filter(df,exp == 2 & value < 0), by= c("name"="name"))[[1]] 

Anche se questo funziona se sembra molto fastidioso e ritengo che tale filtro condizionato si trovi al centro di reshape2 e dplyr ma non riesca a capire come farlo. Qualcuno mi può illuminare qui?

risposta

16

Un'alternativa che viene in mente è quella di trasformare i dati in un formato "largo" e quindi fare il filtraggio.

Ecco un esempio di utilizzo "data.table" (per la comodità dei composti-dichiarazioni):

library(data.table) 
dcast.data.table(as.data.table(df), name ~ exp)[`1` > 0 & `2` < 0] 
#  name 1 2 
# 1: gene2 1 -1 

Allo stesso modo, con "dplyr" e "tidyr":

library(dplyr) 
library(tidyr) 
df %>% 
    spread(exp, value) %>% 
    filter(`1` > 0 & `2` < 0) 
+0

Questa soluzione è così facile e geniale allo stesso tempo! Grazie! Mi ha permesso di imparare molto! A proposito, posso farti una domanda? Perché i nomi delle nuove colonne dovrebbero essere espressi come '\' 1 \ '' invece di ''1'' o' "1" '? Grazie! –

+0

@FranciscoRodriguezAlgarra, non ho provato gli altri, a dire il vero. Generalmente, quando si tratta di nomi di variabili problematici, vado direttamente ai backtick, che è anche raccomandato dalla pagina di aiuto in "? Quote". – A5C1D2H2I1M1N2O1R2T1

+0

@Ananda Mahto, potresti fare un po 'di espirazione sul tuo commento riguardante i backtick - sono i nomi delle variabili che potrebbero essere problematici (dato che hanno nomi "1" e "2")? – user3375672

1

Probabilmente questo è ancora più complicata di quanto la vostra soluzione, ma penso che abbia un tatto "dplyr":

df %>% 
    filter((exp == 1 & value > 0) | (exp == 2 & value < 0)) %>% 
    group_by(name) %>% 
    filter(length(unique(exp)) == 2) %>% 
    select(name) %>% 
    unique() 

#Source: local data frame [1 x 1] 
#Groups: name 

# name 
#1 gene2 
4

Un'altra opzione è dplyr:

group_by(df, name) %>% filter(value[exp == 1] > 0 & value[exp == 2] < 0) 

#Source: local data frame [2 x 3] 
#Groups: name 
# 
# exp name value 
#1 1 gene2  1 
#2 2 gene2 -1 
1

filter consente a più parametri con virgola, sames come select. Ogni condizione in più è un AND:

group_by(df, name) %>% filter(value[exp == 1] > 0, value[exp == 2] < 0)

Da documentazione ufficiale: https://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html

Gli esempi riportati sono:

  • flights[flights$month == 1 & flights$day == 1, ] a base di R

  • filter(flights, month == 1, day == 1) in dplyr .

Problemi correlati