2015-04-23 7 views
9

Ho difficoltà a modificare un sottoinsieme di righe in dplyr. Sto usando il comando di concatenamento: %>% dire:R Come modificare un sottoinsieme di righe

data <- data %>% 
    filter(ColA == "ABC") %>% 
    mutate(ColB = "XXXX") 

Questo funziona bene, ma i problemi è che voglio essere in grado di selezionare l'intera tabella originale e vedere la mutano riservato il sottoinsieme di dati che ho avuto specificato. Il mio problema è che quando visualizzo i dati dopo questo, vedo solo il sottoinsieme di data e le sue informazioni aggiornate ColB.

Vorrei anche sapere come farlo utilizzando data.table.

Grazie.

risposta

9

Utilizzando data.table, faremmo:

setDT(data)[colA == "ABC", ColB := "XXXX"] 

ed i valori vengono modificati sul posto, a differenza if-else, which'd copiare l'intera colonna di sostituire solo le righe in cui la condizione soddisfa.

Chiamiamo questo sub-assign per riferimento. Puoi leggere ulteriori informazioni al riguardo nel numero new HTML vignettes.

+0

Grazie. Questo ha funzionato. E come faccio a fare un filtro di criteri multipli? Ho provato quanto segue ma non sembra la sintassi corretta. SetDT (dati) [(colA == "ABC") & (colC == "DEF"), ColB: = "XXXX"] ' –

+0

@ user1991118 quella * è * la sintassi corretta - forse puoi mostrare un esempio riproducibile. L'unica cosa che riesco a pensare è che forse hai intenzione di usare '|' invece di '&'. – eddi

+0

Questa era effettivamente la sintassi corretta. Avevo usato la variabile sbagliata. Funziona. –

4

Quando si utilizza filter() in realtà si rimuovono le righe che non corrispondono alla condizione specificata, in modo che non vengano visualizzate nel set di dati finale.

Il numero ColB esiste già nella cornice dati? Se è così,

data %>% 
    mutate(ColB = ifelse(ColA == "ABC", "XXXX", ColB)) 

cambierà ColB-"XXXX" quando ColA == "ABC" e lasciarlo come è altrimenti. Se ColB non esiste già, allora si dovrà specificare che cosa fare per le righe in cui ColA != "ABC", ad esempio:

data %>% 
    mutate(ColB = ifelse(ColA == "ABC", "XXXX", NA)) 
0

Un'altra opzione è quella di effettuare una successiva combinazione di unione e anti-join con gli stessi dati. Ciò richiede una chiave primaria:

data <- data %>% 
    filter(ColA == "ABC") %>% 
    mutate(ColB = "XXXX") %>% 
    rbind_list(., anti_join(data, ., by = ...)) 

Esempio:

mtcars_n <- mtcars %>% add_rownames 
mtcars_n %>% 
    filter(cyl > 6) %>% 
    mutate(mpg = 1) %>% 
    rbind_list(., anti_join(mtcars_n, ., by = "rowname")) 

Questo è molto più lento di quanto probabilmente qualsiasi altro approccio, ma utile per ottenere risultati rapidi, estendendo il vostro tubo esistente.