2013-03-05 8 views
32

Ho due set di dati che dovrebbero avere la stessa dimensione ma non lo sono. Ho bisogno di tagliare i valori da A che non sono in B e viceversa per eliminare il rumore da un grafico che sta entrando in un rapporto. (Non ti preoccupare, questo dato non viene eliminato in modo permanente!)Come posso impostare sottoinsieme le righe in un frame di dati in R in base a un vettore di valori?

Ho letto quanto segue:

Ma io' Non riesco ancora a far funzionare correttamente questo Ecco il mio codice:

bg2011missingFromBeg <- setdiff(x=eg2011$ID, y=bg2011$ID) 
#attempt 1 
eg2011cleaned <- subset(eg2011, ID != bg2011missingFromBeg) 
#attempt 2 
eg2011cleaned <- eg2011[!eg2011$ID %in% bg2011missingFromBeg] 

Il primo tentativo elimina solo il primo valore nel vettore setdiff risultante. Il secondo rendimenti cercare di errore ingombrante:

Error in `[.data.frame`(eg2012, !eg2012$ID %in% bg2012missingFromBeg) 
: undefined columns selected 
+0

Hai provato a unire? – A5C1D2H2I1M1N2O1R2T1

+0

Non penso che "unione" sia appropriato qui. Non voglio che i set di dati siano combinati. – Zelbinian

+8

No, penso che "unire" sia esattamente appropriato. Un join interno ti darebbe solo le righe che si trovano sia in A che in B. Puoi quindi subordinare le colonne del risultato se l'unione aggiungesse quelle estranee. – joran

risposta

49

Questo vi darà ciò che si vuole:

eg2011cleaned <- eg2011[!eg2011$ID %in% bg2011missingFromBeg, ] 

L'errore nel secondo tentativo è perché si è dimenticato il ,

In generale, per convenienza, la specifica object[index] sostituisce le colonne per un 2d object. Se si desidera impostare sottoinsiemi e mantenere tutte le colonne, è necessario utilizzare la specifica object[index_rows, index_columns], mentre index_cols può essere lasciato vuoto, che utilizzerà tutte le colonne per impostazione predefinita.

Tuttavia, è comunque necessario includere , per indicare che si desidera ottenere un sottoinsieme di righe anziché un sottoinsieme di colonne.

+0

Sì, questo risolve il problema. Aspetterò altre risposte, però, nel caso qualcuno si inventasse qualcosa di veramente intelligente. :) – Zelbinian

+0

'subset' funzionerà se si modifica l'istruzione logica in' sottoinsieme (ad esempio2011,! ID% in% bg2011missingFromBeg) ' –

+0

Questa è davvero la stessa risposta di quella che ho scritto. Scegli la risposta di adibender, poiché risolve direttamente il tuo problema. Ho solo aggiunto il mio affinché altri possano essere usati come riferimento più affidabile se si imbattono in questa pagina in seguito. – Dinre

14

Se davvero si vuole solo sottoinsieme ogni frame di dati da un indice che esiste in entrambi i frame di dati, si può fare questo con la funzione di 'match', in questo modo:

data_A[match(data_B$index, data_A$index, nomatch=0),] 
data_B[match(data_A$index, data_B$index, nomatch=0),] 

Si tratta, però, lo stesso:

data_A[data_A$index %in% data_B$index,] 
data_B[data_B$index %in% data_A$index,] 

Ecco una demo:

# Set seed for reproducibility. 
set.seed(1) 

# Create two sample data sets. 
data_A <- data.frame(index=sample(1:200, 90, rep=FALSE), value=runif(90)) 
data_B <- data.frame(index=sample(1:200, 120, rep=FALSE), value=runif(120)) 

# Subset data of each data frame by the index in the other. 
t_A <- data_A[match(data_B$index, data_A$index, nomatch=0),] 
t_B <- data_B[match(data_A$index, data_B$index, nomatch=0),] 

# Make sure they match. 
data.frame(t_A[order(t_A$index),], t_B[order(t_B$index),])[1:20,] 

# index  value index.1 value.1 
# 27  3 0.7155661  3 0.65887761 
# 10 12 0.6049333  12 0.14362694 
# 88 14 0.7410786  14 0.42021589 
# 56 15 0.4525708  15 0.78101754 
# 38 18 0.2075451  18 0.70277874 
# 24 23 0.4314737  23 0.78218212 
# 34 32 0.1734423  32 0.85508236 
# 22 38 0.7317925  38 0.56426384 
# 84 39 0.3913593  39 0.09485786 
# 5  40 0.7789147  40 0.31248966 
# 74 43 0.7799849  43 0.10910096 
# 71 45 0.2847905  45 0.26787813 
# 57 46 0.1751268  46 0.17719454 
# 25 48 0.1482116  48 0.99607737 
# 81 53 0.6304141  53 0.26721208 
# 60 58 0.8645449  58 0.96920881 
# 30 59 0.6401010  59 0.67371223 
# 75 61 0.8806190  61 0.69882454 
# 63 64 0.3287773  64 0.36918946 
# 19 70 0.9240745  70 0.11350771 
+0

Fammi vedere se riesco a ripetere 'data_A [dati_A $ indice% in% dati_B $ indice,]' in parole. Dammi tutte le righe in data_A che sono sia in data_A che data_B, in base al loro indice. Ho ragione? – Zelbinian

+3

@Zelbinian In particolare, dice: Dammi tutte le righe in data_A in cui il valore dell'indice delle righe in data_A può essere trovato nei valori dell'indice in data_B. È un'affermazione leggermente diversa, ma è fondamentalmente corretta. L'unica differenza è che vogliamo specificamente i numeri di riga da data_A.Se hai annullato la dichiarazione, non funzionerebbe correttamente. – Dinre

+0

Bel esempio riproducibile + spiegazioni. –

1

per i commenti al post originale, m erges/joins sono adatti per questo problema. In particolare, un join interno restituirà solo i valori presenti in entrambi i dataframes, rendendo superflua l'istruzione setdiff.

Utilizzando i dati dall'esempio di Dinre:

In Base R:

cleanedA <- merge(data_A, data_B[, "index"], by = 1, sort = FALSE) 
cleanedB <- merge(data_B, data_A[, "index"], by = 1, sort = FALSE) 

Usando il pacchetto dplyr:

library(dplyr) 
cleanedA <- inner_join(data_A, data_B %>% select(index)) 
cleanedB <- inner_join(data_B, data_A %>% select(index)) 

Per mantenere i dati come due tabelle separate , ognuno contenente solo le proprie variabili, questo sottopone la tabella indesiderata solo alla sua indice variabile prima di unirsi. Quindi nessuna nuova variabile viene aggiunta alla tabella risultante.

1

davvero umano comprensibile esempio (come questa è la prima volta sto utilizzando% in%), come confrontare due frame di dati e mantenere solo righe contenenti i valori uguali a specifica colonna:

# Set seed for reproducibility. 
set.seed(1) 

# Create two sample data frames. 
data_A <- data.frame(id=c(1,2,3), value=c(1,2,3)) 
data_B <- data.frame(id=c(1,2,3,4), value=c(5,6,7,8)) 

# compare data frames by specific columns and keep only 
# the rows with equal values 
data_A[data_A$id %in% data_B$id,] # will keep data in data_A 
data_B[data_B$id %in% data_A$id,] # will keep data in data_b 

Risultati:

> data_A[data_A$id %in% data_B$id,] 
    id value 
1 1  1 
2 2  2 
3 3  3 

> data_B[data_B$id %in% data_A$id,] 
    id value 
1 1  5 
2 2  6 
3 3  7