data.table
data.table
è una libreria che ci aiuta a fare data management in modo efficiente, come dplyr
. Tuttavia, ci sono alcune importanti differenze tra i due:
dplyr
include funzioni che dipendono da altri pacchetti del tidyverse
, data.table
non ha dipendenze.data.table
è più simile alla sintassi di R base, in quanto utilizza ampiamente le parentesi quadre [
.data.table
è più veloce di dplyr
, e il modo in cui gestisce la memoria e parallelizza alcune operazioni rende data.table
la risorsa ideale nel caso si debba lavorare con database di grandi dimensioni.Nella maggior parte delle applicazioni, la differenza tra data.table
e dplyr
in termini di prestazioni non è così grande. La grammatica di dplyr
è sicuramente più intuitiva, anche se è piuttosto diversa da quella di R base. Tuttavia, data.table
è una risorsa importante ed è utile sapere che esiste.
data.table
è più flessibile di dplyr
, e permette una gamma più ampia di operazioni. Qui ne passeremo in rassegna solo alcune, seguendo lo stesso ordine della scorsa sessione. Per la maggior parte delle operazioni di data management questo è tutto ciò che ci serve.
Il primo passo è sempre quello di installare la libreria. In realtà tutti voi dovreste già averla installata, dato che è una dipendenza di rio
. Ovviamente chi non ha rio
può installare data.table
con il solito comando.
Carichiamo la libreria
Per prima cosa, come al solito, carichiamo i dati. data.table
offre una funzione per leggere i dati, chiamata fread()
che è piuttosto veloce quando si tratta di caricare file di grandi dimensioni. Lo svantaggio è che non legge i dati in qualsiasi formato, come rio
, ma solo alcuni formati tabellari base, il più comune dei quali probabilmente è .csv
. Per questo motivo, ho fatto una copia del nostro file cses2018small
in formato .csv
.
Notare che l’oggetto prodotto con fread()
non è un “data frame”, ma una “data table”. Come per il “tibble” in dplyr
, questo è un formato dati leggermente diverso che è ottimizzato per essere usato con data.table
. Possiamo vedere il formato chiedendo a R la classe dell’oggetto tramite la funzione class()
.
## [1] "data.table" "data.frame"
Naturalmente possiamo sempre caricare i dati usando rio
, tuttavia in questo caso occorre dire a rio
che vogliamo che i dati siano nel formato ottimizzato per data.table
. Possiamo farlo con l’opzione setclass
.
## [1] "data.table" "data.frame"
Infine, possiamo sempre convertire un data frame nel formato compatibile con data.table
usando la funzione as.data.table()
.
Il modo per selezionare le variabili con data.table
è simile a R base, con alcuni miglioramenti. La logica è la stessa della selezione delle colonne negli oggetti bidimensionali. Come abbiamo fatto l’ultima volta, creiamo un nuovo dataset che include solo le variabili mip1
e mip2
dal database cses
.
Selezione “classica” con le parentesi quadre [
come in R base:
## mip1 mip2
## 1: la scuola il lavoro
## 2:
## 3: poverta,lavoro immigrazione
## 4: il lavoro immigrazione
## 5: lavoro immigrazione
## 6: il lavoro l'immigrazione
Se non vogliamo usare le virgolette possiamo anche mettere i nomi delle variabili nella funzione list()
:
## mip1 mip2
## 1: la scuola il lavoro
## 2:
## 3: poverta,lavoro immigrazione
## 4: il lavoro immigrazione
## 5: lavoro immigrazione
## 6: il lavoro l'immigrazione
Che può essere scritta in modo più rapido sostituendo list()
con .()
:
Se la lista di variabili da selezionare è fa parte di un oggetto possiamo selezionare in modo più sofisticato, tuttavia dobbiamo usare due punti ..
:
Perché i due punti? La logica è simile alla sintassi per spostarsi in su e in giù tra le directory in un sistema di tipo Unix. In questo caso, i due punti significano che stiamo cambiando ambiente dall’interno della tabella dati all’ambiente globale (dove si trova l’oggetto vars
).
Anche selezionare osservazioni con data.table
è una versione semplificata di quella di R base. Per esempio, non abbiamo bisogno di mettere la virgola ,
dopo l’espressione che usiamo per selezionare le osservazioni.
Oltre ai soliti operatori logici data.table
offre alcune risorse utili. Un esempio è %chin%
, che è come %in%
ma ottimizzato per lavorare con valori alfanumerici.
Come abbiamo fatto la volta scorsa, selezioniamo solo gli intervistati che vivono nelle regioni del nord, hanno più di 35 anni, e pensano che durante l’anno prima delle elezioni la situazione economica del paese sia peggiorata.
## id sex eta eta_gr mip1 mip2 eco_eval area
## 1: 3 Femmina 68 55+ poverta,lavoro immigrazione -1 Nord-Est
## 2: 5 Femmina 54 35 54 lavoro immigrazione -1 Nord-Ovest
## 3: 20 Femmina 65 55+ lavoro crisi economica -1 Nord-Ovest
## 4: 27 Femmina 57 55+ burocrazia politica -1 Nord-Est
## 5: 35 Femmina 45 35 54 disoccupazione immigrazione -1 Nord-Ovest
## 6: 88 Maschio 51 35 54 sicurezza immigrazione -1 Nord-Est
Possiamo anche selezionare in base a pattern corrispondenti nelle variabili stringa, come abbiamo fatto usando la funzione grep()
. Per esempio, se vogliamo trovare tutti coloro che hanno risposto immigrazione alla domanda sul problema più importante in Italia, possiamo cercare il pattern “migr” nella variabile mip1
e filtrare solo i casi in cui il pattern corrisponde usando l’espressione %like%
– la logica è identica a grep()
.
## id sex eta eta_gr mip1 mip2 eco_eval area
## 1: 9 Femmina 53 35 54 immigrazione costi della politica 1 Sud
## 2: 40 Femmina 39 35 54 Immigrazione Criminalita' 1 Nord-Ovest
## 3: 49 Femmina 69 55+ immigrazione occupazione 1 Nord-Est
## 4: 77 Maschio 67 55+ immigrazione lavoro -1 Centro
## 5: 89 Femmina 50 35 54 Immigrazione Crisi economica 0 Sud
## ---
## 113: 1861 Femmina 39 35 54 immigrazione educazione 0 Nord-Ovest
## 114: 1889 Femmina 49 35 54 immigrazione recessione economica 0 Centro
## 115: 1925 Maschio 42 35 54 immigrati tasse 1 Nord-Est
## 116: 1934 Maschio 67 55+ immigrazione rispettare le regole 0 Nord-Ovest
## 117: 1953 Maschio 69 55+ immigrazione reddito - lavoro -1 Nord-Ovest
Se vogliamo selezionare tutte le osservazioni entro un certo intervallo di valori di una variabile, possiamo usare le espressioni %between%
o %inrange%
. Per esempio, selezioniamo tutti gli intervistati di età compresa tra 30 e 45 anni:
## id sex eta eta_gr mip1 mip2 eco_eval area
## 1: 10 Femmina 37 35 54 la disoccupazione la poverta -1 Sud
## 2: 16 Femmina 33 18 34 sicurezza lavoro -1 Nord-Ovest
## 3: 25 Maschio 35 35 54 lavoro tasse 0 Nord-Est
## 4: 35 Femmina 45 35 54 disoccupazione immigrazione -1 Nord-Ovest
## 5: 36 Femmina 43 35 54 disoccupazione giovanile servizio sanitario -1 Centro
## ---
## 426: 1978 Maschio 35 35 54 lavoro pensioni basse 1 Sud
## 427: 1985 Femmina 42 35 54 la dissocupazione la sicurezza 0 Nord-Ovest
## 428: 1987 Femmina 38 35 54 meritocrazia poverta 0 Centro
## 429: 1990 Femmina 39 35 54 le tasse -1 Nord-Est
## 430: 2000 Femmina 44 35 54 razzismo al livello degli attentati il lavoro -1 Centro
Una caratteristica comoda di data.table
è che possiamo eliminare in modo agevole le osservazioni mancanti solo in alcune variabili. Qualche giorno fa abbiamo visto la funzione na.omit()
di R base, che cancella tutte le osservazioni che hanno almeno un valore mancante in una variabile. Con questa funzione in R base non c’è modo di specificare per quali variabili vogliamo eliminare i valori mancanti, le prende in considerazione necessariamente tutte. data.table
però ha la sua versione di na.omit()
, che permette di specificare per quali variabili vogliamo eliminare i valori mancanti.
Il linguaggio con cui comunicare con data.table
per ricodificare le variabili, sia cambiando i valori delle variabili esistenti che creandone di nuove, implica l’uso del simbolo :=
.
## id sex eta eta_gr mip1 mip2 eco_eval area eta_std
## 1: 1 Femmina 60 55+ la scuola il lavoro -1 Sud 0.5124959
## 2: 2 Maschio 62 55+ -1 Centro 0.6317059
## 3: 3 Femmina 68 55+ poverta,lavoro immigrazione -1 Nord-Est 0.9893360
## 4: 4 Maschio 62 55+ il lavoro immigrazione -1 Sud 0.6317059
## 5: 5 Femmina 54 35 54 lavoro immigrazione -1 Nord-Ovest 0.1548658
## 6: 6 Femmina 71 55+ il lavoro l'immigrazione 0 Nord-Ovest 1.1681511
Possiamo anche ricodificare più valori di una variabile categorica, come con la funzione recode()
di dplyr
. Come al solito, mettiamo assieme Nord-Est e Nord-Ovest in una sola categoria:
cses_pg <- cses[, area2 := c("Nord-Ovest" = "Nord",
"Nord-Est" = "Nord",
"Centro" = "Centro",
"Sud" = "Sud") [area] ]
head(cses_pg)
## id sex eta eta_gr mip1 mip2 eco_eval area eta_std area2
## 1: 1 Femmina 60 55+ la scuola il lavoro -1 Sud 0.5124959 Sud
## 2: 2 Maschio 62 55+ -1 Centro 0.6317059 Centro
## 3: 3 Femmina 68 55+ poverta,lavoro immigrazione -1 Nord-Est 0.9893360 Nord
## 4: 4 Maschio 62 55+ il lavoro immigrazione -1 Sud 0.6317059 Sud
## 5: 5 Femmina 54 35 54 lavoro immigrazione -1 Nord-Ovest 0.1548658 Nord
## 6: 6 Femmina 71 55+ il lavoro l'immigrazione 0 Nord-Ovest 1.1681511 Nord
Naturalmente possiamo accorpare le operazioni di ricodifica all’interno della stessa operazione, mettendo l’operatore :=
prima di scrivere tutte le espressioni di ricodifica:
cses_pg <- cses[, ":="(area2 = c("Nord-Ovest" = "Nord",
"Nord-Est" = "Nord",
"Centro" = "Centro",
"Sud" = "Sud") [area],
eta_std = scale(eta))]
head(cses_pg)
## id sex eta eta_gr mip1 mip2 eco_eval area eta_std area2
## 1: 1 Femmina 60 55+ la scuola il lavoro -1 Sud 0.5124959 Sud
## 2: 2 Maschio 62 55+ -1 Centro 0.6317059 Centro
## 3: 3 Femmina 68 55+ poverta,lavoro immigrazione -1 Nord-Est 0.9893360 Nord
## 4: 4 Maschio 62 55+ il lavoro immigrazione -1 Sud 0.6317059 Sud
## 5: 5 Femmina 54 35 54 lavoro immigrazione -1 Nord-Ovest 0.1548658 Nord
## 6: 6 Femmina 71 55+ il lavoro l'immigrazione 0 Nord-Ovest 1.1681511 Nord
Una cosa importante: ogni volta che utilizziamo il simbolo :=
noi stiamo modificando l’oggetto “data table” esistente, anche se pensiamo di creare un oggetto nuovo. Ad esempio, nel nostro caso le nuove variabili create (area2
e eta_std
) sono presenti anche nel dataset originale!
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area" "eta_std" "area2"
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area" "eta_std" "area2"
Perché questo? Ricordiamo che data.table
è stato pensato per essere usato con dataset molto grandi, nell’ordine di Gigabyte, che in R vengono caricati nella RAM. In questi casi, creare un nuovo oggetto contenente gli stessi dati porterebbe via ulteriore memoria. Per evitare questo, data.table
non crea copie dei dati.
Questa caratteristica fa sì che non ci sia neanche bisogno di usare la freccia <-
quando vogliamo aggiungere variabili a un dataset. Per esempio, creiamo una variabile chiamata neg_eco
con valore \(1\) per chi valuta l’economia dell’anno precedente in modo negativo e \(0\) per tutti gli altri:
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area" "eta_std" "area2" "neg_eco"
Questo comportamento è onnipresente in data.table
, quindi se creiamo un nuovo oggetto contenente il dataset usando la freccia <-
, le modifiche che facciamo a quell’oggetto appariranno anche nel vecchio oggetto!
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area" "eta_std" "area2" "neg_eco" "teen"
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area" "eta_std" "area2" "neg_eco" "teen"
Questo succede ogni volta che usiamo l’operatore :=
, che è l’operatore che usiamo per creare nuove variabili nel dataset.
Come facciamo se non vogliamo modificare l’oggetto iniziale? Se vogliamo fare una copia del dataset, come nel caso dell’oggetto cses_pg
, dobbiamo utilizzare la funzione copy()
:
Ora possiamo fare delle modifiche all’oggetto cses_pg
, evitando che tali modifiche si propaghino all’oggetto originale cses
:
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area" "eta_std" "area2" "neg_eco" "teen" "elder"
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area" "eta_std" "area2" "neg_eco" "teen"
In questo esercizio vogliamo mantenere il dataset originale identico a come l’abbiamo caricato, quindi eliminiamo le nuove variabili che abbiamo appena creato nel nostro oggetto cses_pg
credendo di non modificare anche cses
.
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area"
Queste variabili ora rimangono in cses_pg
## [1] "id" "sex" "eta" "eta_gr" "mip1" "mip2" "eco_eval" "area" "eta_std" "area2" "neg_eco" "teen" "elder"
Applicare funzioni per gruppo (come le variabili di centratura del gruppo che abbiamo visto la volta scorsa) è molto facile in data.table
. Per farlo è sufficiente aggiungere l’opzione by
alla fine della ricodifica. Si può usare un singolo fattore di raggruppamento o più di uno:
# Raggruppando per area
cses_pg[, eta_std := scale(eta), by = "area"]
with(cses_pg, plot(eta, eta_std))
# Raggruppando per area e genere
cses_pg[, eta_std := scale(eta), by = c("area", "sex")]
with(cses_pg, plot(eta, eta_std))
Lo stesso risultato si ottiene con la funzione keyby
:
Con data.table
è relativamente facile creare oggetti contenenti aggregazioni dei dati come con summarize()
in dplyr
. Anche in questo caso si utilizzano le funzioni list()
o .()
(notare che in questo caso non usiamo l’operatore :=
).
## eta_m
## 1: 51.4018
## [1] 51.4018
Ovviamente è altrettanto facile ottenere dati aggregati per gruppo:
## area eta_m
## 1: Sud 48.75038
## 2: Centro 51.79372
## 3: Nord-Est 53.57307
## 4: Nord-Ovest 52.84629
La volta scorsa abbiamo visto come in dplyr
sia possibile concatenare le diverse operazioni che eseguiamo sui dati usando l’operatore pipe %>%
. Con data.table
possiamo scrivere espressioni complesse (cioè espressioni che includono tutte le operazioni che dobbiamo eseguire, come ricodifiche, selezione di osservazioni e variabili, ecc.) all’interno della stessa operazione, definita dalle parentesi quadre [ ... ]
. Tuttavia, possiamo anche concatenare espressioni come in dplyr
, semplicemente scrivendo diverse operazioni in sequenza: DT[ ... ][ ... ][ ... ][ ... ]
.
cses_gr <- copy(cses)
cses_gr <- cses_gr[, ":="(area2 = c("Nord-Ovest" = "Nord",
"Nord-Est" = "Nord",
"Centro" = "Centro",
"Sud" = "Sud") [area])][, # Qui iniziamo la seconda operazione
keyby = c("area2", "eta_gr"),
.(m_eco = mean(eco_eval, na.rm = TRUE))]
cses_gr
## area2 eta_gr m_eco
## 1: Centro 18 34 -0.07407407
## 2: Centro 35 54 -0.19078947
## 3: Centro 55+ -0.01941748
## 4: Nord 18 34 0.13636364
## 5: Nord 35 54 -0.08013937
## 6: Nord 55+ 0.05111111
## 7: Sud 18 34 -0.13375796
## 8: Sud 35 54 -0.23529412
## 9: Sud 55+ -0.16600791
dtplyr
Nella scorsa sessione abbiamo visto le funzioni più importanti di dplyr
, una libreria che sta diventando molto popolare tra gli utenti di R. Oggi abbiamo visto alcune funzioni di data.table
, un’altra libreria per fare data management che funziona molto bene (cioè in modo rapido) con dataset di grandi dimensioni. Tra i due, dplyr
vince chiaramente in termini di chiarezza e ordine della sintassi. D’altra parte, data.table
vince in termini di prestazioni (anche se la differenza tra i due diventa apparente solo quando si utilizzano dataset molto grandi).
Partendo da una considerazione di questo tipo, qualcuno ha pensato che sarebbe bello avere un pacchetto che combini il front end di dplyr
con il back end di data.table
, traducendo le funzioni di dplyr
nel linguaggio di data.table
e usando quest’ultimo per eseguire le operazioni in background. Ecco quindi dtplyr
, una libreria sviluppata dal team di sviluppo del tidyverse
.
dtplyr
funziona in modo relativamente semplice: le funzioni sono le stesse di dplyr
, l’unica differenza è che dobbiamo convertire il nostro oggetto dati in un “lazy data table”. In questo modo, dtplyr
saprà che le funzioni di dplyr
che stiamo scrivendo dovranno essere tradotte in data.table
ed eseguite sull’oggetto “lazy data table”.
Iniziamo installando e caricando la libreria. Dobbiamo anche caricare dplyr
, dato che la maggior parte delle funzioni provengono da lì.
Ora dobbiamo fare solo 2 cose. Prima di tutto, trasformiamo il nostro oggetto in un “lazy data table” con la funzione lazy_dt()
:
Notare che l’oggetto cses2
è considerato una “lista”, non un data frame (o tibble, o data table). Questo perchè l’oggetto non contiene solo i dati, ma anche diverse altre informazioni che dtplyr
usa per convertire le funzioni di dplyr
nel linguaggio di data.table
.
Notare anche che se chiediamo a R di mostrarci l’oggetto, riusciremo a vedere sia i dati che il comando di data.table
usato per mostrare i dati:
## Source: local data table [?? x 8]
## Call: head(`_DT1`, n = 6L)
##
## id sex eta eta_gr mip1 mip2 eco_eval area
## <int> <chr> <int> <chr> <chr> <chr> <int> <chr>
## 1 1 Femmina 60 55+ "la scuola" "il lavoro" -1 Sud
## 2 2 Maschio 62 55+ "" "" -1 Centro
## 3 3 Femmina 68 55+ "poverta,lavoro" "immigrazione" -1 Nord-Est
## 4 4 Maschio 62 55+ "il lavoro" "immigrazione" -1 Sud
## 5 5 Femmina 54 35 54 "lavoro" "immigrazione" -1 Nord-Ovest
## 6 6 Femmina 71 55+ "il lavoro" "l'immigrazione" 0 Nord-Ovest
##
## # Use as.data.table()/as.data.frame()/as_tibble() to access results
dtplyr
ci mostra anche un messaggio che ci spiega come possiamo accedere ai dati: dobbiamo convertire l’oggetto lazy_dt
in un oggetto dati, che sia un “data frame”, “tibble” o “data table”:
## # A tibble: 6 x 8
## id sex eta eta_gr mip1 mip2 eco_eval area
## <int> <chr> <int> <chr> <chr> <chr> <int> <chr>
## 1 1 Femmina 60 55+ "la scuola" "il lavoro" -1 Sud
## 2 2 Maschio 62 55+ "" "" -1 Centro
## 3 3 Femmina 68 55+ "poverta,lavoro" "immigrazione" -1 Nord-Est
## 4 4 Maschio 62 55+ "il lavoro" "immigrazione" -1 Sud
## 5 5 Femmina 54 35 54 "lavoro" "immigrazione" -1 Nord-Ovest
## 6 6 Femmina 71 55+ "il lavoro" "l'immigrazione" 0 Nord-Ovest
Questa è la seconda cosa che dobbiamo fare con dtplyr
: dopo aver svolto tutte le operazioni di data management, dobbiamo ricordarci di estrarre i dati dall’oggetto, aggiungendo alla fine della catena di operazioni una funzione per convertirlo in un dataset. Possiamo quindi usare le funzioni as_tibble()
o as.data.frame()
o as.data.table()
per ottenere i dati nel formato che preferiamo.
cses_gr <- cses2 %>%
select(eta_gr, area, eco_eval) %>%
filter(eta_gr %in% c("18 34", "55+")) %>%
mutate(
area2 = recode(area,
"Nord-Ovest" = "Nord",
"Nord-Est" = "Nord",
"Centro" = "Centro",
"Sud" = "Sud")
) %>%
group_by(area2, eta_gr) %>%
summarize(
m_eco = mean(eco_eval, na.rm = TRUE)
) %>%
as.data.frame()
cses_gr
## area2 eta_gr m_eco
## 1 Centro 18 34 -0.07407407
## 2 Centro 55+ -0.01941748
## 3 Nord 18 34 0.13636364
## 4 Nord 55+ 0.05111111
## 5 Sud 18 34 -0.13375796
## 6 Sud 55+ -0.16600791
Ovviamente se chiediamo a R di mostrarci l’oggetto “lazy data table” senza convertirlo in un oggetto dati prima, dtplyr
mostrerà anche la sintassi che data.table
usa per eseguire le operazioni chieste in linguaggio dplyr
. Questo può anche tornare utile per vedere le equivalenze tra i due linguaggi, e impararli entrambi.
cses2 %>%
select(eta_gr, area, eco_eval) %>%
filter(eta_gr %in% c("18 34", "55+")) %>%
mutate(
area2 = recode(area,
"Nord-Ovest" = "Nord",
"Nord-Est" = "Nord",
"Centro" = "Centro",
"Sud" = "Sud")
) %>%
group_by(area2, eta_gr) %>%
summarize(
m_eco = mean(eco_eval, na.rm = TRUE)
)
## Source: local data table [?? x 3]
## Call: `_DT1`[, .(eta_gr, area, eco_eval)][eta_gr %in% c("18 34", "55+")][,
## `:=`(area2 = recode(area, `Nord-Ovest` = "Nord", `Nord-Est` = "Nord",
## Centro = "Centro", Sud = "Sud"))][, .(m_eco = mean(eco_eval,
## na.rm = TRUE)), keyby = .(area2, eta_gr)]
##
## area2 eta_gr m_eco
## <chr> <chr> <dbl>
## 1 Centro 18 34 -0.0741
## 2 Centro 55+ -0.0194
## 3 Nord 18 34 0.136
## 4 Nord 55+ 0.0511
## 5 Sud 18 34 -0.134
## 6 Sud 55+ -0.166
##
## # Use as.data.table()/as.data.frame()/as_tibble() to access results
dtplyr
Quanto guadagnamo in termini di velocità usando dtplyr
invece che dplyr
? Come si è detto sopra, data.table
da il meglio di sé quando ha a che fare con dataset molto grandi. Con dataset “normali” (diciamo qualche migliaia di osservazioni e centinaia di variabili) il valore aggiunto di avere un back end come quello di data.table
è relativamente limitato.
Per fare un esempio, proviamo a paragonare la performance di dplyr
e dtplyr
in una serie di semplici operazioni fatte sui dati cses
, e chiedendo un data frame come risultato in entrambi i casi.
Possiamo misurare quanto tempo R impiega a svolgere una determinata operazione usando la funzione system.time()
:
# Creiamo un lazy data table per `dtplyr`
cses2 <- lazy_dt(cses)
# Creiamo un tibble `dplyr`
cses3 <- as_tibble(cses)
# Performance di `dtplyr`
system.time(
cses2 %>%
filter(eta_gr %in% c("18 34", "55+")) %>%
mutate(
area2 = recode(area,
"Nord-Ovest" = "Nord",
"Nord-Est" = "Nord",
"Centro" = "Centro",
"Sud" = "Sud")
) %>%
group_by(area2, eta_gr) %>%
summarize(
m_eco = mean(eco_eval, na.rm = TRUE)
) %>%
as.data.frame()
)
## user system elapsed
## 0.004 0.000 0.004
# Performance di `dplyr`
system.time(
cses3 %>%
filter(eta_gr %in% c("18 34", "55+")) %>%
mutate(
area2 = recode(area,
"Nord-Ovest" = "Nord",
"Nord-Est" = "Nord",
"Centro" = "Centro",
"Sud" = "Sud")
) %>%
group_by(area2, eta_gr) %>%
summarize(
m_eco = mean(eco_eval, na.rm = TRUE)
) %>%
as.data.frame()
)
## `summarise()` has grouped output by 'area2'. You can override using the `.groups` argument.
## user system elapsed
## 0.020 0.001 0.021