Potenzia i tuoi dati con R

Pubblicato: 2022-03-11

Il linguaggio R è spesso percepito come un linguaggio per statistici e data scientist. Molto tempo fa, questo era per lo più vero. Tuttavia, nel corso degli anni la flessibilità fornita da R tramite i pacchetti ha reso R un linguaggio più generico. R era open source nel 1995 e da allora i repository di pacchetti R sono in costante crescita. Tuttavia, rispetto a linguaggi come Python, R è fortemente basato sui dati.

Parlando di dati, i dati tabulari meritano un'attenzione particolare, in quanto sono uno dei tipi di dati più comunemente usati. È un tipo di dati che corrisponde a una struttura di tabella nota nei database, in cui ogni colonna può essere di un tipo diverso e le prestazioni di elaborazione di quel particolare tipo di dati sono il fattore cruciale per molte applicazioni.

R può essere utilizzato per un efficiente scambio di dati di dati tabulari

R può essere utilizzato per un efficiente scambio di dati di dati tabulari
Twitta

In questo articolo, presenteremo come ottenere la trasformazione dei dati tabulari in modo efficiente. Molte persone che usano già R per l'apprendimento automatico non sono consapevoli del fatto che il data munging può essere eseguito più velocemente in R e che non è necessario utilizzare un altro strumento per questo.

Soluzione ad alte prestazioni in R

Base R ha introdotto la classe data.frame nell'anno 1997, che era basata su S-PLUS prima di essa. A differenza dei database comunemente usati che archiviano i dati riga per riga, R data.frame archivia i dati in memoria come una struttura orientata alle colonne, rendendo così più efficiente la cache per le operazioni sulle colonne comuni nell'analisi. Inoltre, anche se R è un linguaggio di programmazione funzionale, non lo impone allo sviluppatore. Entrambe le opportunità sono state ben affrontate dal pacchetto data.table R, disponibile nel repository CRAN. Funziona abbastanza velocemente durante il raggruppamento delle operazioni ed è particolarmente efficiente in termini di memoria prestando attenzione alla materializzazione di sottoinsiemi di dati intermedi, come la materializzazione solo di quelle colonne necessarie per una determinata attività. Evita anche copie non necessarie attraverso la sua semantica di riferimento durante l'aggiunta o l'aggiornamento di colonne. La prima versione del pacchetto è stata pubblicata nell'aprile 2006, migliorando notevolmente le prestazioni di data.frame in quel momento. La descrizione iniziale del pacchetto era:

Questo pacchetto fa molto poco. L'unico motivo della sua esistenza è che il libro bianco specifica che data.frame deve avere nomi di riga. Questo pacchetto definisce una nuova classe data.table che funziona proprio come un data.frame, ma utilizza fino a 10 volte meno memoria e può essere fino a 10 volte più veloce da creare (e copiare). Sfrutta anche l'opportunità di consentire espressioni simili a subset() e with() all'interno di []. La maggior parte del codice viene copiata dalle funzioni di base con il codice che manipola row.names rimosso.

Da allora, sia le implementazioni data.frame che data.table sono state migliorate, ma data.table rimane incredibilmente più veloce della base R. In effetti, data.table non è solo più veloce della base R, ma sembra essere una del più veloce strumento di gestione dei dati open source disponibile, in competizione con strumenti come Python Pandas e database di archiviazione a colonne o app per big data come Spark. Le sue prestazioni sull'infrastruttura condivisa distribuita non sono state ancora confrontate, ma essere in grado di avere fino a due miliardi di righe su una singola istanza offre prospettive promettenti. Le prestazioni eccezionali vanno di pari passo con le funzionalità. Inoltre, con i recenti sforzi per parallelizzare le parti che richiedono tempo per aumentare le prestazioni, sembra abbastanza chiara una direzione per spingere il limite delle prestazioni.

Esempi di trasformazione dei dati

L'apprendimento di R diventa un po' più semplice grazie al fatto che funziona in modo interattivo, quindi possiamo seguire gli esempi passo dopo passo e guardare i risultati di ogni passaggio in qualsiasi momento. Prima di iniziare, installiamo il pacchetto data.table dal repository CRAN.

 install.packages("data.table")

Suggerimento utile : Possiamo aprire il manuale di qualsiasi funzione semplicemente digitandone il nome con un punto interrogativo iniziale, ad esempio ?install.packages .

Caricamento dei dati in R

Esistono tonnellate di pacchetti per estrarre dati da un'ampia gamma di formati e database, che spesso includono driver nativi. Caricheremo i dati dal file CSV , il formato più comune per i dati tabulari grezzi. Il file utilizzato nei seguenti esempi può essere trovato qui. Non dobbiamo preoccuparci delle prestazioni di lettura CSV poiché la funzione fread è altamente ottimizzata su questo.

Per utilizzare qualsiasi funzione da un pacchetto, è necessario caricarlo con la chiamata alla library .

 library(data.table) DT <- fread("flights14.csv") print(DT)
 ## year month day dep_delay arr_delay carrier origin dest air_time ## 1: 2014 1 1 14 13 AA JFK LAX 359 ## 2: 2014 1 1 -3 13 AA JFK LAX 363 ## 3: 2014 1 1 2 9 AA JFK LAX 351 ## 4: 2014 1 1 -8 -26 AA LGA PBI 157 ## 5: 2014 1 1 2 1 AA JFK LAX 350 ## --- ## 253312: 2014 10 31 1 -30 UA LGA IAH 201 ## 253313: 2014 10 31 -5 -14 UA EWR IAH 189 ## 253314: 2014 10 31 -8 16 MQ LGA RDU 83 ## 253315: 2014 10 31 -4 15 MQ LGA DTW 75 ## 253316: 2014 10 31 -5 1 MQ LGA SDF 110 ## distance hour ## 1: 2475 9 ## 2: 2475 11 ## 3: 2475 19 ## 4: 1035 7 ## 5: 2475 13 ## --- ## 253312: 1416 14 ## 253313: 1400 8 ## 253314: 431 11 ## 253315: 502 11 ## 253316: 659 8

Se i nostri dati non sono ben modellati per un'ulteriore elaborazione, poiché devono essere rimodellati dal formato long-to-wide o wide-to-long (noto anche come pivot e unpivot ), potremmo esaminare ?dcast e ?melt , noto dal pacchetto reshape2. Tuttavia, data.table implementa metodi più veloci ed efficienti in termini di memoria per la classe data.table/data.frame.

Interrogazione con la sintassi data.table

Se hai familiarità con data.frame

Query data.table è molto simile a query data.frame . Durante il filtraggio nell'argomento i , possiamo usare i nomi delle colonne direttamente senza la necessità di accedervi con il segno $ , come df[df$col > 1, ] . Quando forniamo l'argomento successivo j , forniamo un'espressione da valutare nell'ambito del nostro data.table . Per passare un argomento j non di espressione, utilizzare with=FALSE . Il terzo argomento, non presente nel metodo data.frame , definisce i gruppi, facendo in modo che l'espressione in j venga valutata dai gruppi.

 # data.frame DF[DF$col1 > 1L, c("col2", "col3")] # data.table DT[col1 > 1L, .(col2, col3), ...] # by group using: `by = col4`

Se hai familiarità con i database

Query data.table in molti aspetti corrisponde a query SQL con cui più persone potrebbero avere familiarità. DT di seguito rappresenta l'oggetto data.table e corrisponde alla clausola SQL FROM .

 DT[ i = where, j = select | update, by = group by] [ having, ... ] [ order by, ... ] [ ... ] ... [ ... ] 

Districare i dati tabluari

Ordinamento di righe e riordino di colonne

L'ordinamento dei dati è una trasformazione cruciale per le serie temporali e anche l'importazione per l'estrazione e la presentazione dei dati. L'ordinamento può essere ottenuto fornendo il vettore intero dell'ordine delle righe all'argomento i , allo stesso modo di data.frame . Il primo argomento order(carrier, -dep_delay) selezionerà i dati in ordine crescente sul campo del carrier e in ordine decrescente sulla misura dep_delay . Il secondo argomento j , come descritto nella sezione precedente, definisce le colonne (o espressioni) da restituire e il loro ordine.

 ans <- DT[order(carrier, -dep_delay), .(carrier, origin, dest, dep_delay)] head(ans)
 ## carrier origin dest dep_delay ## 1: AA EWR DFW 1498 ## 2: AA JFK BOS 1241 ## 3: AA EWR DFW 1071 ## 4: AA EWR DFW 1056 ## 5: AA EWR DFW 1022 ## 6: AA EWR DFW 989

Per riordinare i dati per riferimento, invece di interrogare i dati in un ordine specifico, utilizziamo le funzioni set* .

 setorder(DT, carrier, -dep_delay) leading.cols <- c("carrier","dep_delay") setcolorder(DT, c(leading.cols, setdiff(names(DT), leading.cols))) print(DT)
 ## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## --- ## 253312: WN -12 2014 3 9 -21 LGA BNA 115 ## 253313: WN -13 2014 3 10 -18 EWR MDW 112 ## 253314: WN -13 2014 5 17 -30 LGA HOU 202 ## 253315: WN -13 2014 6 15 10 LGA MKE 101 ## 253316: WN -13 2014 8 19 -30 LGA CAK 63 ## distance hour ## 1: 1372 7 ## 2: 187 13 ## 3: 1372 10 ## 4: 1372 6 ## 5: 1372 7 ## --- ## 253312: 764 16 ## 253313: 711 20 ## 253314: 1428 17 ## 253315: 738 20 ## 253316: 397 16

Molto spesso, non abbiamo bisogno sia del set di dati originale che del set di dati ordinato/ordinato. Per impostazione predefinita, il linguaggio R, simile ad altri linguaggi di programmazione funzionale, restituirà i dati ordinati come nuovo oggetto e quindi richiederà il doppio della memoria rispetto all'ordinamento per riferimento.

Query sottoinsiemi

Creiamo un set di dati di sottoinsieme per l'origine del volo "JFK" e il mese da 6 a 9. Nel secondo argomento, sottoponiamo i risultati alle colonne elencate, aggiungendo una variabile calcolata sum_delay .

 ans <- DT[origin == "JFK" & month %in% 6:9, .(origin, month, arr_delay, dep_delay, sum_delay = arr_delay + dep_delay)] head(ans)
 ## origin month arr_delay dep_delay sum_delay ## 1: JFK 7 925 926 1851 ## 2: JFK 8 727 772 1499 ## 3: JFK 6 466 451 917 ## 4: JFK 7 414 450 864 ## 5: JFK 6 411 442 853 ## 6: JFK 6 333 343 676

Per impostazione predefinita, quando si imposta il set di dati su una singola colonna data.table creerà automaticamente un indice per quella colonna. Ciò si traduce in risposte in tempo reale su eventuali ulteriori chiamate di filtraggio su quella colonna.

Aggiorna set di dati

L'aggiunta di una nuova colonna per riferimento viene eseguita utilizzando l'operatore := , assegna una variabile al set di dati in atto. Ciò evita la copia in memoria del set di dati, quindi non è necessario assegnare risultati a ogni nuova variabile.

 DT[, sum_delay := arr_delay + dep_delay] head(DT)
 ## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## 6: AA 989 2014 6 11 991 EWR DFW 194 ## distance hour sum_delay ## 1: 1372 7 2992 ## 2: 187 13 2464 ## 3: 1372 10 2135 ## 4: 1372 6 2171 ## 5: 1372 7 2095 ## 6: 1372 11 1980

Per aggiungere più variabili contemporaneamente, possiamo usare la sintassi DT[, := (sum_delay = arr_delay + dep_delay)] , simile a .(sum_delay = arr_delay + dep_delay) quando si esegue una query dal set di dati.

È possibile sub-assegnare per riferimento, aggiornando solo determinate righe sul posto, semplicemente combinando con i argomento.

 DT[origin=="JFK", distance := NA] head(DT)
 ## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## 6: AA 989 2014 6 11 991 EWR DFW 194 ## distance hour sum_delay ## 1: 1372 7 2992 ## 2: NA 13 2464 ## 3: 1372 10 2135 ## 4: 1372 6 2171 ## 5: 1372 7 2095 ## 6: 1372 11 1980

Dati aggregati

Per aggregare i dati, forniamo il terzo argomento by parentesi quadre. Quindi, in j dobbiamo fornire chiamate di funzioni aggregate, in modo che i dati possano essere effettivamente aggregati. Il simbolo .N utilizzato nell'argomento j corrisponde al numero di tutte le osservazioni in ciascun gruppo. Come accennato in precedenza, gli aggregati possono essere combinati con sottoinsiemi su righe e selezionando colonne.

 ans <- DT[, .(m_arr_delay = mean(arr_delay), m_dep_delay = mean(dep_delay), count = .N), .(carrier, month)] head(ans)
 ## carrier month m_arr_delay m_dep_delay count ## 1: AA 10 5.541959 7.591497 2705 ## 2: AA 4 1.903324 3.987008 2617 ## 3: AA 6 8.690067 11.476475 2678 ## 4: AA 9 -1.235160 3.307078 2628 ## 5: AA 8 4.027474 8.914054 2839 ## 6: AA 7 9.159886 11.665953 2802

Spesso, potrebbe essere necessario confrontare un valore di una riga con il suo aggregato su un gruppo. In SQL, applichiamo aggregati sulla partizione per : AVG(arr_delay) OVER (PARTITION BY carrier, month) .

 ans <- DT[, .(arr_delay, carrierm_mean_arr = mean(arr_delay), dep_delay, carrierm_mean_dep = mean(dep_delay)), .(carrier, month)] head(ans)
 ## carrier month arr_delay carrierm_mean_arr dep_delay carrierm_mean_dep ## 1: AA 10 1494 5.541959 1498 7.591497 ## 2: AA 10 840 5.541959 848 7.591497 ## 3: AA 10 317 5.541959 338 7.591497 ## 4: AA 10 292 5.541959 331 7.591497 ## 5: AA 10 322 5.541959 304 7.591497 ## 6: AA 10 306 5.541959 299 7.591497

Se non vogliamo interrogare i dati con quegli aggregati e invece inserirli semplicemente nell'aggiornamento effettivo della tabella per riferimento, possiamo farlo con l'operatore := . Ciò evita la copia in memoria del set di dati, quindi non è necessario assegnare risultati alla nuova variabile.

 DT[, `:=`(carrierm_mean_arr = mean(arr_delay), carrierm_mean_dep = mean(dep_delay)), .(carrier, month)] head(DT)
 ## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## 6: AA 989 2014 6 11 991 EWR DFW 194 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep ## 1: 1372 7 2992 5.541959 7.591497 ## 2: NA 13 2464 1.903324 3.987008 ## 3: 1372 10 2135 8.690067 11.476475 ## 4: 1372 6 2171 -1.235160 3.307078 ## 5: 1372 7 2095 8.690067 11.476475 ## 6: 1372 11 1980 8.690067 11.476475

Unisciti ai set di dati

L'unione e l'unione di base R di insiemi di dati è considerata un tipo speciale di operazione di sottoinsiemi . Forniamo un set di dati a cui vogliamo unire nel primo argomento parentesi quadre i . Per ogni riga nel set di dati fornito a i , abbiniamo le righe del set di dati in cui utilizziamo [ . Se vogliamo mantenere solo le righe corrispondenti ( inner join ), allora passiamo un argomento extra nomatch = 0L . Usiamo on argument per specificare le colonne su cui vogliamo unire entrambi i set di dati.

 # create reference subset carrierdest <- DT[, .(count=.N), .(carrier, dest) # count by carrier and dest ][1:10 # just 10 first groups ] # chaining `[...][...]` as subqueries print(carrierdest)
 ## carrier dest count ## 1: AA DFW 5877 ## 2: AA BOS 1173 ## 3: AA ORD 4798 ## 4: AA SEA 298 ## 5: AA EGE 85 ## 6: AA LAX 3449 ## 7: AA MIA 6058 ## 8: AA SFO 1312 ## 9: AA AUS 297 ## 10: AA DCA 172
 # outer join ans <- carrierdest[DT, on = c("carrier","dest")] print(ans)
 ## carrier dest count dep_delay year month day arr_delay origin ## 1: AA DFW 5877 1498 2014 10 4 1494 EWR ## 2: AA BOS 1173 1241 2014 4 15 1223 JFK ## 3: AA DFW 5877 1071 2014 6 13 1064 EWR ## 4: AA DFW 5877 1056 2014 9 12 1115 EWR ## 5: AA DFW 5877 1022 2014 6 16 1073 EWR ## --- ## 253312: WN BNA NA -12 2014 3 9 -21 LGA ## 253313: WN MDW NA -13 2014 3 10 -18 EWR ## 253314: WN HOU NA -13 2014 5 17 -30 LGA ## 253315: WN MKE NA -13 2014 6 15 10 LGA ## 253316: WN CAK NA -13 2014 8 19 -30 LGA ## air_time distance hour sum_delay carrierm_mean_arr ## 1: 200 1372 7 2992 5.541959 ## 2: 39 NA 13 2464 1.903324 ## 3: 175 1372 10 2135 8.690067 ## 4: 198 1372 6 2171 -1.235160 ## 5: 178 1372 7 2095 8.690067 ## --- ## 253312: 115 764 16 -33 6.921642 ## 253313: 112 711 20 -31 6.921642 ## 253314: 202 1428 17 -43 22.875845 ## 253315: 101 738 20 -3 14.888889 ## 253316: 63 397 16 -43 7.219670 ## carrierm_mean_dep ## 1: 7.591497 ## 2: 3.987008 ## 3: 11.476475 ## 4: 3.307078 ## 5: 11.476475 ## --- ## 253312: 11.295709 ## 253313: 11.295709 ## 253314: 30.546453 ## 253315: 24.217560 ## 253316: 17.038047
 # inner join ans <- DT[carrierdest, # for each row in carrierdest nomatch = 0L, # return only matching rows from both tables on = c("carrier","dest")] # joining on columns carrier and dest print(ans)
 ## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1071 2014 6 13 1064 EWR DFW 175 ## 3: AA 1056 2014 9 12 1115 EWR DFW 198 ## 4: AA 1022 2014 6 16 1073 EWR DFW 178 ## 5: AA 989 2014 6 11 991 EWR DFW 194 ## --- ## 23515: AA -8 2014 10 11 -13 JFK DCA 53 ## 23516: AA -9 2014 5 21 -12 JFK DCA 52 ## 23517: AA -9 2014 6 5 -6 JFK DCA 53 ## 23518: AA -9 2014 10 2 -21 JFK DCA 51 ## 23519: AA -11 2014 5 27 10 JFK DCA 55 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep count ## 1: 1372 7 2992 5.541959 7.591497 5877 ## 2: 1372 10 2135 8.690067 11.476475 5877 ## 3: 1372 6 2171 -1.235160 3.307078 5877 ## 4: 1372 7 2095 8.690067 11.476475 5877 ## 5: 1372 11 1980 8.690067 11.476475 5877 ## --- ## 23515: NA 15 -21 5.541959 7.591497 172 ## 23516: NA 15 -21 4.150172 8.733665 172 ## 23517: NA 15 -15 8.690067 11.476475 172 ## 23518: NA 15 -30 5.541959 7.591497 172 ## 23519: NA 15 -1 4.150172 8.733665 172

Tieni presente che, a causa della coerenza con il sottoinsieme R di base, il join esterno è per impostazione predefinita RIGHT OUTER . Se stiamo cercando LEFT OUTER , dobbiamo scambiare le tabelle, come nell'esempio sopra. Il comportamento esatto può anche essere facilmente controllato nel metodo merge data.table , utilizzando la stessa API di base R merge data.frame .

Se vogliamo semplicemente cercare le colonne nel nostro set di dati, possiamo farlo in modo efficiente con l'operatore := nell'argomento j durante l'unione. Allo stesso modo in cui sub-assegnamo per riferimento, come descritto nella sezione Aggiorna set di dati, solo ora aggiungiamo una colonna per riferimento dal set di dati a cui ci uniamo. Ciò evita la copia in memoria dei dati, quindi non è necessario assegnare i risultati a nuove variabili.

 DT[carrierdest, # data.table to join with lkp.count := count, # lookup `count` column from `carrierdest` on = c("carrier","dest")] # join by columns head(DT)
 ## carrier dep_delay year month day arr_delay origin dest air_time ## 1: AA 1498 2014 10 4 1494 EWR DFW 200 ## 2: AA 1241 2014 4 15 1223 JFK BOS 39 ## 3: AA 1071 2014 6 13 1064 EWR DFW 175 ## 4: AA 1056 2014 9 12 1115 EWR DFW 198 ## 5: AA 1022 2014 6 16 1073 EWR DFW 178 ## 6: AA 989 2014 6 11 991 EWR DFW 194 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep lkp.count ## 1: 1372 7 2992 5.541959 7.591497 5877 ## 2: NA 13 2464 1.903324 3.987008 1173 ## 3: 1372 10 2135 8.690067 11.476475 5877 ## 4: 1372 6 2171 -1.235160 3.307078 5877 ## 5: 1372 7 2095 8.690067 11.476475 5877 ## 6: 1372 11 1980 8.690067 11.476475 5877

Per aggregare mentre unisciti , usa by = .EACHI . Esegue unioni che non materializzeranno risultati di join intermedi e applicherà gli aggregati al volo, rendendo la memoria efficiente.

Il rolling join è una funzionalità non comune, progettata per gestire i dati ordinati. Si adatta perfettamente all'elaborazione di dati temporali e serie temporali in generale. Fondamentalmente esegue il rollio delle partite in condizione di unione al valore di corrispondenza successivo. Usalo fornendo l'argomento roll quando ti unisci.

L'unione a sovrapposizione rapida unisce i set di dati in base ai periodi e alla relativa gestione della sovrapposizione utilizzando vari operatori sovrapposti: any , within , start , end .

È attualmente in fase di sviluppo una funzione di join non equi per unire set di dati utilizzando condizioni non uguali.

Dati di profilazione

Quando esploriamo il nostro set di dati, a volte potremmo voler raccogliere informazioni tecniche sull'argomento, per comprendere meglio la qualità dei dati.

Statistiche descrittive

 summary(DT)
 ## carrier dep_delay year month ## Length:253316 Min. :-112.00 Min. :2014 Min. : 1.000 ## Class :character 1st Qu.: -5.00 1st Qu.:2014 1st Qu.: 3.000 ## Mode :character Median : -1.00 Median :2014 Median : 6.000 ## Mean : 12.47 Mean :2014 Mean : 5.639 ## 3rd Qu.: 11.00 3rd Qu.:2014 3rd Qu.: 8.000 ## Max. :1498.00 Max. :2014 Max. :10.000 ## ## day arr_delay origin dest ## Min. : 1.00 Min. :-112.000 Length:253316 Length:253316 ## 1st Qu.: 8.00 1st Qu.: -15.000 Class :character Class :character ## Median :16.00 Median : -4.000 Mode :character Mode :character ## Mean :15.89 Mean : 8.147 ## 3rd Qu.:23.00 3rd Qu.: 15.000 ## Max. :31.00 Max. :1494.000 ## ## air_time distance hour sum_delay ## Min. : 20.0 Min. : 80.0 Min. : 0.00 Min. :-224.00 ## 1st Qu.: 86.0 1st Qu.: 529.0 1st Qu.: 9.00 1st Qu.: -19.00 ## Median :134.0 Median : 762.0 Median :13.00 Median : -5.00 ## Mean :156.7 Mean : 950.4 Mean :13.06 Mean : 20.61 ## 3rd Qu.:199.0 3rd Qu.:1096.0 3rd Qu.:17.00 3rd Qu.: 23.00 ## Max. :706.0 Max. :4963.0 Max. :24.00 Max. :2992.00 ## NA's :81483 ## carrierm_mean_arr carrierm_mean_dep lkp.count ## Min. :-22.403 Min. :-4.500 Min. : 85 ## 1st Qu.: 2.676 1st Qu.: 7.815 1st Qu.:3449 ## Median : 6.404 Median :11.354 Median :5877 ## Mean : 8.147 Mean :12.465 Mean :4654 ## 3rd Qu.: 11.554 3rd Qu.:17.564 3rd Qu.:6058 ## Max. : 86.182 Max. :52.864 Max. :6058 ## NA's :229797

Cardinalità

Possiamo verificare l'unicità dei dati utilizzando la funzione uniqueN e applicarla su ogni colonna. L'oggetto .SD nella query seguente corrisponde al sottoinsieme della tabella dati:

 DT[, lapply(.SD, uniqueN)]
 ## carrier dep_delay year month day arr_delay origin dest air_time ## 1: 14 570 1 10 31 616 3 109 509 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep lkp.count ## 1: 152 25 1021 134 134 11

Rapporto NA

Per calcolare il rapporto di valori sconosciuti ( NA in R e NULL in SQL) per ciascuna colonna, forniamo la funzione desiderata da applicare su ogni colonna.

 DT[, lapply(.SD, function(x) sum(is.na(x))/.N)]
 ## carrier dep_delay year month day arr_delay origin dest air_time ## 1: 0 0 0 0 0 0 0 0 0 ## distance hour sum_delay carrierm_mean_arr carrierm_mean_dep lkp.count ## 1: 0.3216654 0 0 0 0 0.9071555

Esportazione di dati

Il pacchetto data.table fornisce anche un'esportazione rapida di dati tabulari in formato CSV .

 tmp.csv <- tempfile(fileext=".csv") fwrite(DT, tmp.csv) # preview exported data cat(system(paste("head -3",tmp.csv), intern=TRUE), sep="\n")
 ## carrier,dep_delay,year,month,day,arr_delay,origin,dest,air_time,distance,hour,sum_delay,carrierm_mean_arr,carrierm_mean_dep,lkp.count ## AA,1498,2014,10,4,1494,EWR,DFW,200,1372,7,2992,5.54195933456561,7.59149722735674,5877 ## AA,1241,2014,4,15,1223,JFK,BOS,39,,13,2464,1.90332441727168,3.98700802445548,1173

Al momento della stesura di questo, la funzione fwrite non è stata ancora pubblicata nel repository CRAN. Per usarlo dobbiamo installare la versione di sviluppo data.table , altrimenti possiamo usare la funzione di base R write.csv , ma non aspettarti che sia veloce.

Risorse

Ci sono molte risorse disponibili. Oltre ai manuali disponibili per ciascuna funzione, ci sono anche le vignette dei pacchetti, che sono tutorial incentrati su un argomento particolare. Questi possono essere trovati nella pagina per iniziare. Inoltre, la pagina Presentazioni elenca più di 30 materiali (diapositive, video, ecc.) da presentazioni data.table in tutto il mondo. Inoltre, il supporto della community è cresciuto nel corso degli anni, raggiungendo di recente la 4000esima domanda sul tag Stack Overflow data.table , con un rapporto ancora elevato (91,9%) di domande con risposta. Il grafico seguente presenta il numero di domande contrassegnate da data.table su Stack Overflow nel tempo.

Domande SO mensili per data.table - Solo domande con tag data.table, non quelle con risposte data.table (accettate)

Domande SO mensili per data.table - Solo domande con tag data.table, non quelle con risposte data.table (accettate)

Sommario

Questo articolo fornisce esempi scelti per un'efficiente trasformazione dei dati tabulari in R usando il pacchetto data.table . I dati effettivi sulle prestazioni possono essere esaminati cercando benchmark riproducibili. Ho pubblicato un post sul blog riepilogativo sulle soluzioni data.table per le 50 principali domande StackOverflow classificate per il linguaggio R chiamato Risolvi problemi R comuni in modo efficiente con data.table, dove puoi trovare molte cifre e codice riproducibile. Il pacchetto data.table utilizza l'implementazione nativa dell'ordinamento rapido di radix per le sue operazioni di raggruppamento e la ricerca binaria di sottoinsiemi/join veloci. Questo ordinamento radix è stato incorporato nella base R dalla versione 3.3.0. Inoltre, l'algoritmo è stato recentemente implementato nella piattaforma di machine learning H2O e parallelizzato su cluster H2O, consentendo big join efficienti su righe 10B x 10B.

Correlati: Manipolazione definitiva della raccolta dei dati in memoria con Supergroup.js