Continuiamo la discussione iniziata in questo post, dove Davide spiegava una procedura per incrociare due tabelle di dati come le due seguenti:
library(tidyverse) ragione_sociale <- c("comune paperopoli", "canile pluto", "archimede pitagorico") codice_cliente <- c(12345, 67890, 54321) servizi <- c(4, 5, 2) servizi_disattivati <- tibble(ragione_sociale, codice_cliente, servizi)
Tabella clienti
ragione_sociale | codice_cliente | agente |
---|---|---|
CANILE DI PLUTO | 67890 | paperino |
ArchimedePitagorico | 54321 | gastone |
Comune di Paperopoli | 12345 | paperoga |
Tabella servizi disattivati
ragione_sociale | codice_cliente | servizi |
---|---|---|
comune paperopoli | 12345 | 4 |
canile pluto | 67890 | 5 |
archimede pitagorico | 54321 | 2 |
L’obiettivo era quello di aggiungere alla tabella servizi_disattivati la variabile agente appartenente alla tabella clienti, usando come riferimento la variabile codice_cliente comune ad entrambe le tabelle. Il risultato desiderato è il seguente:
ragione_sociale | codice_cliente | servizi | agente |
---|---|---|---|
comune paperopoli | 12345 | 4 | paperoga |
canile pluto | 67890 | 5 | paperino |
archimede pitagorico | 54321 | 2 | gastone |
Il pacchetto dplyr ci permette di svolgere tale operazione utilizzando le funzioni inner_join e select. Applicata alle nostre tabelle, data la variabile di riferimento codice_cliente, inner_join restituisce tutte le righe di servizi_disattivati corrispondenti a quelle di clienti. Tuttavia tutte le colonne delle tabelle verranno mantenute, per cui se applicassimo solo inner_join otterremmo:
servizi_disattivati %>% inner_join(clienti, by = "codice_cliente")
ragione_sociale.x | codice_cliente | servizi | ragione_sociale.y | agente |
---|---|---|---|---|
comune paperopoli | 12345 | 4 | Comune di Paperopoli | paperoga |
canile pluto | 67890 | 5 | CANILE DI PLUTO | paperino |
archimede pitagorico | 54321 | 2 | ArchimedePitagorico | gastone |
Dato che in questo caso le variabili ragione_sociale possiedono valori equivalenti anche se non identici, possiamo decidere di mantenere solo una di queste. Per fare ciò, prima di applicare inner_join scartiamo la variabile ragione_sociale dalla tabella clienti:
servizi_disattivati %>% inner_join(clienti %>% select(-ragione_sociale), by = "codice_cliente")
ragione_sociale | codice_cliente | servizi | agente |
---|---|---|---|
comune paperopoli | 12345 | 4 | paperoga |
canile pluto | 67890 | 5 | paperino |
archimede pitagorico | 54321 | 2 | gastone |
Uno dei vantaggi più grandi derivanti dall’utilizzo di inner_join è la sua velocità. Per esempio, proviamo a replicare servizi_disattivati per 500000 volte (ottenendo una tabella di 1500000 righe) e poi misuriamo il tempo impiegato dalla funzione merge per completare l’operazione:
start <- proc.time() servizi_disattivati %>% slice(rep(row_number(), 500000)) %>% merge(clienti %>% select(-ragione_sociale), by.x="codice_cliente", by.y="codice_cliente") proc.time()[3] - start[3]
elapsed
33.686
E ora proviamo con inner_join:
start <- proc.time() servizi_disattivati %>% slice(rep(row_number(), 500000)) %>% inner_join(clienti %>% select(-ragione_sociale), by = "codice_cliente") proc.time()[3] - start[3]
elapsed
0.515
In questo caso inner_join risulta circa 65 volte più veloce di merge. Non male!