Archivio tag: merge

Incrociare due tabelle: dplyr::inner_join vs merge

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!