2014-09-03 21 views
35

Ho un data.frame con dati di carattere in una delle colonne. Vorrei filtrare più opzioni nello data.frame dalla stessa colonna. C'è un modo semplice per fare questo che mi manca?Filtro condizioni multiple dplyr

Esempio: data.frame name = dat

days  name 
88  Lynn 
11   Tom 
2   Chris 
5   Lisa 
22  Kyla 
1   Tom 
222  Lynn 
2   Lynn 

vorrei filtrare Tom e Lynn per esempio.
Quando faccio:

target <- c("Tom", "Lynn") 
filt <- filter(dat, name == target) 

ottengo questo errore:

longer object length is not a multiple of shorter object length 

risposta

101

È necessario %in% invece di ==:

library(dplyr) 
target <- c("Tom", "Lynn") 
filter(dat, name %in% target) # equivalently, dat %>% filter(name %in% target) 

Produce

days name 
1 88 Lynn 
2 11 Tom 
3 1 Tom 
4 222 Lynn 
5 2 Lynn 

Per capire perché, consideriamo cosa succede qui:

dat$name == target 
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE 

In sostanza, stiamo riciclando i due lunghezza target vettore quattro volte in base alla lunghezza del dat$name. In altre parole, stiamo facendo:

Lynn == Tom 
    Tom == Lynn 
Chris == Tom 
Lisa == Lynn 
... continue repeating Tom and Lynn until end of data frame 

In questo caso non si ottiene un errore perché ho il sospetto che la cornice di dati ha in realtà un diverso numero di righe che non permettono il riciclo, ma il campione vi forniamo fa (8 righe). Se il campione avesse avuto un numero dispari di righe, avrei ricevuto lo stesso errore di te. Ma anche quando il riciclaggio funziona, questo non è chiaramente quello che vuoi. Fondamentalmente, l'istruzione dat$name == target equivale a dire:

return TRUE for every odd value that is equal to "Tom" or every even value that is equal to "Lynn".

Accade così che l'ultimo valore nel frame di dati campione è uniforme e uguale a "Lynn", quindi quello TRUE sopra.

Per contrastare, dat$name %in% target dice:

for each value in dat$name , check that it exists in target .

Molto diverso. Ecco il risultato:

[1] TRUE TRUE FALSE FALSE FALSE TRUE TRUE TRUE 

Nota il problema non ha nulla a che fare con dplyr, solo il mis-uso di ==.

+0

Grazie per la spiegazione Brodie! Apprezzo davvero questo, clinico che cerca di capire R! –

7

Usando il pacchetto base:

df <- data.frame(days = c(88, 11, 2, 5, 22, 1, 222, 2), name = c("Lynn", "Tom", "Chris", "Lisa", "Kyla", "Tom", "Lynn", "Lynn")) 

# Three lines 
target <- c("Tom", "Lynn") 
index <- df$name %in% target 
df[index, ] 

# One line 
df[df$name %in% c("Tom", "Lynn"), ] 

uscita:

days name 
1 88 Lynn 
2 11 Tom 
6 1 Tom 
7 222 Lynn 
8 2 Lynn 

Uso sqldf:

library(sqldf) 
# Two alternatives: 
sqldf('SELECT * 
     FROM df 
     WHERE name = "Tom" OR name = "Lynn"') 
sqldf('SELECT * 
     FROM df 
     WHERE name IN ("Tom", "Lynn")') 
2

Ciò può essere ottenuto utilizzando dplyr pacchetto, che è disponibile in CRAN. Il modo più semplice per raggiungere questo obiettivo:

  1. Installare dplyr pacchetto.

  2. library(dplyr) df<- select(filter(dat,name=='tom'| name=='Lynn',c('days','name))

Spiegazione:

Quindi, una volta che abbiamo scaricato dplyr, creiamo un nuovo fotogramma di dati utilizzando due diverse funzioni di questo pacchetto:

filtro: il il primo argomento è il frame dei dati; il secondo argomento è la condizione in base alla quale vogliamo che sia sottosposta. Il risultato è l'intero frame di dati con solo le righe che volevamo. selezionare: il primo argomento è il frame di dati; il secondo argomento sono i nomi delle colonne che vogliamo selezionare da esso. Non è necessario utilizzare la funzione names() e non è nemmeno necessario utilizzare le virgolette. Semplicemente elenciamo i nomi delle colonne come oggetti.