Îmbunătățiți-vă acumularea datelor cu R
Publicat: 2022-03-11Limbajul R este adesea perceput ca un limbaj pentru statisticieni și oamenii de știință de date. Cu mult timp în urmă, acest lucru era în mare parte adevărat. Cu toate acestea, de-a lungul anilor, flexibilitatea oferită de R prin intermediul pachetelor a făcut din R un limbaj de uz mai general. R a fost open source în 1995 și, de atunci, depozitele de pachete R sunt în continuă creștere. Totuși, în comparație cu limbaje precum Python, R se bazează puternic pe date.
Vorbind despre date, datele tabulare merită o atenție deosebită, deoarece este unul dintre tipurile de date cel mai frecvent utilizate. Este un tip de date care corespunde unei structuri de tabel cunoscute în bazele de date, în care fiecare coloană poate fi de un tip diferit, iar performanța de procesare a acelui tip de date este factorul crucial pentru multe aplicații.
În acest articol, vom prezenta cum să obținem transformarea datelor tabulare într-un mod eficient. Mulți oameni care folosesc deja R pentru învățarea automată nu știu că colectarea datelor se poate face mai rapid în R și că nu trebuie să folosească un alt instrument pentru aceasta.
Soluție de înaltă performanță în R
Base R a introdus clasa data.frame
în anul 1997, care era bazată pe S-PLUS înainte. Spre deosebire de bazele de date utilizate în mod obișnuit, care stochează date rând cu rând, R data.frame
stochează datele în memorie ca o structură orientată pe coloană, făcând astfel mai eficientă cache-ul pentru operațiunile pe coloană care sunt comune în analiză. În plus, chiar dacă R este un limbaj de programare funcțional, nu îl impune dezvoltatorului. Ambele oportunități au fost bine abordate de pachetul data.table
R, care este disponibil în depozitul CRAN. Funcționează destul de rapid la gruparea operațiunilor și este deosebit de eficient în memorie, fiind atent la materializarea subseturilor de date intermediare, cum ar fi materializarea numai a acelor coloane necesare pentru o anumită sarcină. De asemenea, evită copiile inutile prin semantica sa de referință în timp ce adaugă sau actualizează coloane. Prima versiune a pachetului a fost publicată în aprilie 2006, îmbunătățind semnificativ performanța data.frame
la acel moment. Descrierea inițială a pachetului a fost:
Acest pachet face foarte puțin. Singurul motiv pentru existența sa este că cartea albă specifică că data.frame trebuie să aibă nume de rânduri. Acest pachet definește o nouă clasă data.table care funcționează la fel ca un data.frame, dar utilizează de până la 10 ori mai puțină memorie și poate fi de până la 10 ori mai rapid pentru a crea (și a copia). De asemenea, profită de ocazie pentru a permite subset() și cu() expresii similare în interiorul []. Majoritatea codului este copiat din funcțiile de bază, cu codul care manipulează row.names eliminat.
De atunci, atât implementările data.frame
, cât și data.table
au fost îmbunătățite, dar data.table
rămâne incredibil de rapid decât baza R. De fapt, data.table
nu este doar mai rapid decât baza R, dar pare a fi unul. dintre cel mai rapid instrument de dispută de date open-source disponibil, concurând cu instrumente precum Python Pandas și baze de date de stocare în coloană sau aplicații de date mari precum Spark. Performanța sa asupra infrastructurii partajate distribuite nu a fost încă evaluată, dar posibilitatea de a avea până la două miliarde de rânduri pe o singură instanță oferă perspective promițătoare. Performanța remarcabilă merge mână în mână cu funcționalitățile. În plus, odată cu eforturile recente de paralelizare a pieselor consumatoare de timp pentru câștiguri incrementale de performanță, o direcție către împingerea limitei de performanță pare destul de clară.
Exemple de transformare a datelor
Învățarea R devine puțin mai ușoară datorită faptului că funcționează interactiv, așa că putem urma exemple pas cu pas și să privim oricând rezultatele fiecărui pas. Înainte de a începe, să instalăm pachetul data.table
din depozitul CRAN.
install.packages("data.table")
Sugestie utilă : Putem deschide manualul oricărei funcții doar tastând numele acesteia cu semnul principal de întrebare, adică ?install.packages
.
Încărcarea datelor în R
Există o mulțime de pachete pentru extragerea datelor dintr-o gamă largă de formate și baze de date, care includ adesea drivere native. Vom încărca datele din fișierul CSV , cel mai comun format pentru datele brute tabelare. Fișierul folosit în următoarele exemple poate fi găsit aici. Nu trebuie să ne deranjam cu privire la performanța citirii CSV
, deoarece funcția fread
este foarte optimizată în acest sens.
Pentru a folosi orice funcție dintr-un pachet, trebuie să o încărcăm cu apelul la 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
Dacă datele noastre nu sunt bine modelate pentru procesare ulterioară, deoarece acestea trebuie remodelate din formatul lung la lat sau lat la lung (cunoscut și sub numele de pivot și unpivot ), putem analiza ?dcast
și ?melt
, cunoscut din pachetul reshape2. Cu toate acestea, data.table
implementează metode mai rapide și eficiente de memorie pentru clasa data.table/data.frame.
Interogare cu data.table
Sintaxă
Dacă sunteți familiarizat cu data.frame
Query data.table
este foarte asemănător cu query data.frame
. În timp ce filtrăm în argumentul i
, putem folosi numele coloanelor direct, fără a fi nevoie să le accesăm cu semnul $
, cum ar fi df[df$col > 1, ]
. Când furnizam următorul argument j
, oferim o expresie care trebuie evaluată în sfera data.table
. Pentru a transmite un argument non-expresie j
utilizați with=FALSE
. Al treilea argument, neprezent în metoda data.frame
, definește grupurile, făcând ca expresia din j
să fie evaluată de grupuri.
# data.frame DF[DF$col1 > 1L, c("col2", "col3")] # data.table DT[col1 > 1L, .(col2, col3), ...] # by group using: `by = col4`
Dacă sunteți familiarizat cu bazele de date
Query data.table
în multe aspecte corespunde interogărilor SQL cu care mai mulți oameni ar putea fi familiarizați. DT
de mai jos reprezintă obiectul data.table
și corespunde clauzei SQL-uri FROM
.
DT[ i = where, j = select | update, by = group by] [ having, ... ] [ order by, ... ] [ ... ] ... [ ... ]
Sortarea rândurilor și reordonarea coloanelor
Sortarea datelor este o transformare crucială pentru seriile de timp și este, de asemenea, importuri pentru extragerea și prezentarea datelor. Sortarea poate fi realizată furnizând vectorul întreg al ordinii rândurilor la argumentul i
, în același mod ca data.frame
. Primul argument în order(carrier, -dep_delay)
va selecta datele în ordine crescătoare în câmpul carrier
și în ordine descrescătoare pe măsura dep_delay
. Al doilea argument j
, așa cum este descris în secțiunea anterioară, definește coloanele (sau expresiile) care trebuie returnate și ordinea acestora.
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
Pentru a reordona datele prin referință, în loc să interogăm datele în ordine specifică, folosim funcții 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
Cel mai adesea, nu avem nevoie atât de setul de date original, cât și de setul de date ordonat/sortat. În mod implicit, limbajul R, similar altor limbaje de programare funcționale, va returna datele sortate ca obiect nou și, astfel, va necesita de două ori mai multă memorie decât sortarea prin referință.
Subset Interogări
Să creăm un subset de date pentru originea zborului „JFK” și luna de la 6 la 9. În al doilea argument, subsetăm rezultatele în coloanele listate, adăugând o variabilă calculată 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
În mod implicit, la subsetarea setului de date pe o singură coloană, data.table
va crea automat un index pentru acea coloană. Acest lucru are ca rezultat răspunsuri în timp real pentru orice alte apeluri de filtrare din acea coloană.
Actualizați setul de date
Adăugarea unei noi coloane prin referință se realizează folosind operatorul :=
, acesta atribuie o variabilă în setul de date în loc. Acest lucru evită copierea în memorie a setului de date, deci nu trebuie să atribuim rezultate fiecărei variabile noi.
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
Pentru a adăuga mai multe variabile simultan, putem folosi sintaxa DT[,
:= (sum_delay = arr_delay + dep_delay)]
, similară cu .(sum_delay = arr_delay + dep_delay)
când interogăm din setul de date.
Este posibil să sub-atribuiți prin referință, actualizând numai anumite rânduri în loc, doar combinând cu argumentul i
.
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
Date agregate
Pentru a agrega datele, oferim cel de-al treilea argument by
paranteza pătrată. Apoi, în j
trebuie să furnizăm apeluri de funcții agregate, astfel încât datele să poată fi de fapt agregate. Simbolul .N
folosit în argumentul j
corespunde numărului tuturor observațiilor din fiecare grup. După cum sa menționat anterior, agregatele pot fi combinate cu subseturi pe rânduri și coloane de selectare.
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
Adesea, poate fi nevoie să comparăm o valoare a unui rând cu agregatul său pe un grup. În SQL, aplicăm agregate peste partiția după : 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
Dacă nu dorim să interogăm datele cu acele agregate și, în schimb, le punem doar în actualizarea reală a tabelului prin referință, putem realiza asta cu operatorul :=
. Acest lucru evită copia în memorie a setului de date, deci nu trebuie să atribuim rezultate noii 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
Alăturați-vă seturi de date
Unirea și îmbinarea bazei R a seturilor de date este considerată un tip special de operație de subseturi . Oferim un set de date la care dorim să îl alăturăm în primul argument i
. Pentru fiecare rând din setul de date furnizat către i
, potrivim rândurile din setul de date în care folosim [
. Dacă vrem să păstrăm doar rândurile care se potrivesc ( inner join ), atunci trecem un argument suplimentar nomatch = 0L
. Folosim on
argument pentru a specifica coloanele pe care dorim să unim ambele seturi de date.
# 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
Rețineți că, din cauza coerenței cu subsetarea de bază R, îmbinarea exterioară este implicit RIGHT OUTER
. Dacă căutăm LEFT OUTER
, trebuie să schimbăm tabelele, ca în exemplul de mai sus. Comportamentul exact poate fi, de asemenea, controlat cu ușurință în metoda merge
data.table
, folosind același API ca baza R merge
data.frame
.
Dacă vrem să căutăm pur și simplu coloanele în setul de date, o putem face eficient cu operatorul :=
în argumentul j
în timp ce ne alăturăm. În același mod în care sub-alocam prin referință, așa cum este descris în secțiunea Actualizare setul de date , tocmai acum adăugăm o coloană prin referință din setul de date la care ne alăturăm. Acest lucru evită copierea în memorie a datelor, deci nu este nevoie să atribuim rezultate în variabile noi.
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
Pentru agregare while join , utilizați by = .EACHI
. Realizează îmbinări care nu vor materializa rezultate intermediare de îmbinare și va aplica agregate din mers, făcându-l eficient în memorie.
Rolling join este o caracteristică neobișnuită, concepută pentru a trata datele comandate. Se potrivește perfect pentru prelucrarea datelor temporale și a seriilor temporale în general. Practic, rulează potriviri în condiția de alăturare la următoarea valoare de potrivire. Folosiți-l furnizând argumentul roll
când vă alăturați.
Unirea prin suprapunere rapidă unește seturi de date bazate pe perioade și gestionarea suprapunerii, folosind diferiți operatori care se suprapun: any
, within
, start
, end
.
În prezent, este în curs de dezvoltare o funcție non-equi join pentru a se alătura seturi de date folosind condiția non-equi.
Date de profilare
Când ne explorăm setul de date, uneori putem dori să colectăm informații tehnice despre subiect, pentru a înțelege mai bine calitatea datelor.
Statisticile descriptive
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
Cardinalitatea
Putem verifica unicitatea datelor folosind funcția uniqueN
și o putem aplica pe fiecare coloană. Obiectul .SD
din interogarea de mai jos corespunde subsetului din tabelul de date:
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
Raportul NA
Pentru a calcula raportul valorilor necunoscute ( NA
în R și NULL
în SQL) pentru fiecare coloană, oferim funcția dorită de aplicat pe fiecare coloană.
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
Exportarea datelor
Exportul rapid de date tabulare în format CSV
este oferit și de pachetul data.table
.
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
La momentul scrierii acestui articol, funcția fwrite
nu a fost încă publicată în depozitul CRAN. Pentru ao folosi trebuie să instalăm versiunea de dezvoltare data.table
, altfel putem folosi funcția de bază R write.csv
, dar nu vă așteptați să fie rapid.
Resurse
Există o mulțime de resurse disponibile. Pe lângă manualele disponibile pentru fiecare funcție, există și viniete de pachete, care sunt tutoriale axate pe un anumit subiect. Acestea pot fi găsite pe pagina Noțiuni de bază. În plus, pagina Prezentări listează mai mult de 30 de materiale (diapozitive, video etc.) din prezentări data.table
de pe tot globul. De asemenea, suportul comunității a crescut de-a lungul anilor, ajungând recent la a 4000-a întrebare pe eticheta Stack Overflow data.table
, având încă un raport ridicat (91,9%) de întrebări cu răspuns. Graficul de mai jos prezintă numărul de întrebări etichetate data.table
pe Stack Overflow de-a lungul timpului.
rezumat
Acest articol oferă exemple alese pentru transformarea eficientă a datelor tabulare în R folosind pachetul data.table
. Cifrele reale ale performanței pot fi examinate prin căutarea unor repere reproductibile. Am publicat o postare rezumată pe blog despre soluțiile data.table
pentru cele mai bune 50 de întrebări StackOverflow pentru limbajul R numită Rezolvați eficient problemele comune R cu data.table, unde puteți găsi o mulțime de cifre și cod reproductibil. Pachetul data.table
folosește implementarea nativă a ordonării rapide radix pentru operațiunile sale de grupare și căutare binară pentru subseturi/joinuri rapide. Această ordine de bază a fost încorporată în baza R din versiunea 3.3.0. În plus, algoritmul a fost implementat recent în platforma de învățare automată H2O și paralelizat peste clusterul H2O, permițând îmbinări mari eficiente pe rânduri de 10B x 10B.