Steigern Sie Ihr Daten-Munging mit R

Veröffentlicht: 2022-03-11

Die R-Sprache wird oft als Sprache für Statistiker und Datenwissenschaftler wahrgenommen. Vor langer Zeit war dies meistens der Fall. Im Laufe der Jahre hat die Flexibilität, die R über Pakete bietet, R jedoch zu einer allgemeineren Sprache gemacht. R wurde 1995 als Open Source veröffentlicht, und seit dieser Zeit wachsen die Repositories von R-Paketen ständig. Im Vergleich zu Sprachen wie Python basiert R jedoch stark auf Daten.

Apropos Daten: Tabellendaten verdienen besondere Aufmerksamkeit, da sie einer der am häufigsten verwendeten Datentypen sind. Es ist ein Datentyp, der einer aus Datenbanken bekannten Tabellenstruktur entspricht, wobei jede Spalte von einem anderen Typ sein kann und die Verarbeitungsleistung dieses bestimmten Datentyps für viele Anwendungen der entscheidende Faktor ist.

R kann für eine sehr effiziente Datenverarbeitung von tabellarischen Daten verwendet werden

R kann für eine sehr effiziente Datenverarbeitung von tabellarischen Daten verwendet werden
Twittern

In diesem Artikel stellen wir vor, wie Sie eine tabellarische Datentransformation auf effiziente Weise erreichen können. Viele Menschen, die R bereits für maschinelles Lernen verwenden, sind sich nicht bewusst, dass das Daten-Munging in R schneller durchgeführt werden kann und dass sie dafür kein anderes Tool verwenden müssen.

Hochleistungslösung in R

Base R führte im Jahr 1997 die Klasse data.frame ein, die zuvor auf S-PLUS basierte. Im Gegensatz zu häufig verwendeten Datenbanken, die Daten Zeile für Zeile speichern, speichert R data.frame die Daten im Arbeitsspeicher als spaltenorientierte Struktur, wodurch es für Spaltenoperationen, die in der Analytik üblich sind, Cache-effizienter wird. Obwohl R eine funktionale Programmiersprache ist, erzwingt es dies dem Entwickler nicht. Beide Möglichkeiten wurden durch das R-Paket data.table gut adressiert, das im CRAN-Repository verfügbar ist. Es arbeitet ziemlich schnell beim Gruppieren von Operationen und ist besonders speichereffizient, da es bei der Materialisierung von Zwischendatenteilmengen vorsichtig ist, z. B. indem nur die Spalten materialisiert werden, die für eine bestimmte Aufgabe erforderlich sind. Es vermeidet auch unnötige Kopien durch seine Referenzsemantik beim Hinzufügen oder Aktualisieren von Spalten. Die erste Version des Pakets wurde im April 2006 veröffentlicht und verbesserte die damalige Leistung von data.frame erheblich. Die anfängliche Paketbeschreibung lautete:

Dieses Paket macht sehr wenig. Der einzige Grund für seine Existenz ist, dass das Whitebook festlegt, dass data.frame Zeilennamen haben muss. Dieses Paket definiert eine neue Klasse data.table, die genau wie ein data.frame funktioniert, aber bis zu 10-mal weniger Speicher benötigt und bis zu 10-mal schneller erstellt (und kopiert) werden kann. Es nutzt auch die Gelegenheit, subset()- und with()-ähnliche Ausdrücke innerhalb von [] zuzulassen. Der größte Teil des Codes wird aus Basisfunktionen kopiert, wobei der Code, der row.names manipuliert, entfernt wurde.

Seitdem wurden sowohl data.frame als data.table Implementierungen verbessert, aber data.table ist nach wie vor unglaublich schneller als Basis-R. Tatsächlich ist data.table nicht nur schneller als Basis-R, sondern scheint auch eine zu sein des schnellsten verfügbaren Open-Source-Data-Wrangling-Tools und konkurriert mit Tools wie Python Pandas und spaltenbasierten Speicherdatenbanken oder Big-Data-Apps wie Spark. Seine Leistung über eine verteilte gemeinsam genutzte Infrastruktur wurde noch nicht bewertet, aber die Möglichkeit, bis zu zwei Milliarden Zeilen auf einer einzigen Instanz zu haben, bietet vielversprechende Aussichten. Hervorragende Leistung geht Hand in Hand mit den Funktionalitäten. Darüber hinaus scheint angesichts der jüngsten Bemühungen um die Parallelisierung zeitaufwändiger Teile für inkrementelle Leistungssteigerungen eine Richtung zur Ausweitung der Leistungsgrenze ziemlich klar zu sein.

Beispiele für Datentransformationen

Das Erlernen von R wird etwas einfacher, da es interaktiv funktioniert, sodass wir Beispielen Schritt für Schritt folgen und jederzeit die Ergebnisse der einzelnen Schritte betrachten können. Bevor wir beginnen, installieren wir das Paket data.table aus dem CRAN-Repository.

 install.packages("data.table")

Nützlicher Hinweis : Wir können das Handbuch jeder Funktion öffnen, indem Sie einfach ihren Namen mit führendem Fragezeichen eingeben, dh ?install.packages .

Laden von Daten in R

Es gibt unzählige Pakete zum Extrahieren von Daten aus einer Vielzahl von Formaten und Datenbanken, die häufig native Treiber enthalten. Wir laden Daten aus der CSV -Datei, dem gängigsten Format für tabellarische Rohdaten. Die in den folgenden Beispielen verwendete Datei finden Sie hier. Wir müssen uns nicht um die CSV -Leseleistung kümmern, da die fread Funktion darauf stark optimiert ist.

Um eine beliebige Funktion aus einem Paket zu verwenden, müssen wir sie mit dem library laden.

 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

Wenn unsere Daten für die weitere Verarbeitung nicht gut modelliert sind, da sie vom Long-to-Wide- oder Wide-to-Long-Format (auch bekannt als Pivot und Unpivot ) umgeformt werden müssen, können wir uns die Funktionen ?dcast und ?melt ansehen, bekannt aus dem Paket reshape2. data.table implementiert jedoch schnellere und speichereffizientere Methoden für die Klasse data.table/data.frame.

Abfragen mit data.table Syntax

Wenn Sie mit data.frame vertraut sind

Abfrage data.table ist Abfrage data.frame sehr ähnlich. Beim Filtern im i -Argument können wir Spaltennamen direkt verwenden, ohne auf sie mit dem $ -Zeichen zugreifen zu müssen, wie z. B. df[df$col > 1, ] . Wenn wir das nächste Argument j angeben, stellen wir einen Ausdruck bereit, der im Rahmen unserer data.table ausgewertet werden soll. Um ein j -Argument zu übergeben, das kein Ausdruck ist, verwenden with=FALSE . Das dritte Argument, das in der data.frame Methode nicht vorhanden ist, definiert die Gruppen, wodurch der Ausdruck in j nach Gruppen ausgewertet wird.

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

Wenn Sie mit Datenbanken vertraut sind

Query data.table entspricht in vielerlei Hinsicht SQL-Abfragen, mit denen möglicherweise mehr Menschen vertraut sind. DT unten stellt das data.table Objekt dar und entspricht der FROM -Klausel von SQL.

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

Tabellendaten entwirren

Zeilen sortieren und Spalten neu anordnen

Das Sortieren von Daten ist eine entscheidende Transformation für Zeitreihen, und es ist auch ein Import für die Datenextraktion und -präsentation. Die Sortierung kann erreicht werden, indem der ganzzahlige Vektor der Zeilenreihenfolge für das Argument i bereitgestellt wird, genau wie bei data.frame . Das erste Argument in order(carrier, -dep_delay) wählt Daten in aufsteigender Reihenfolge im carrier Feld und in absteigender Reihenfolge im dep_delay Maß aus. Das zweite Argument j definiert, wie im vorherigen Abschnitt beschrieben, die zurückzugebenden Spalten (oder Ausdrücke) und ihre Reihenfolge.

 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

Um Daten nach Referenz neu zu ordnen, verwenden wir set* -Funktionen, anstatt Daten in einer bestimmten Reihenfolge abzufragen.

 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

Meistens benötigen wir nicht sowohl den ursprünglichen Datensatz als auch den geordneten/sortierten Datensatz. Standardmäßig gibt die Sprache R, ähnlich wie andere funktionale Programmiersprachen, sortierte Daten als neues Objekt zurück und benötigt daher doppelt so viel Speicher wie das Sortieren nach Referenz.

Teilmengenabfragen

Lassen Sie uns einen Teildatensatz für den Flugursprung „JFK“ und den Monat von 6 bis 9 erstellen. Im zweiten Argument unterteilen wir die Ergebnisse in aufgelistete Spalten und fügen eine berechnete Variable 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

Standardmäßig erstellt data.table automatisch einen Index für diese Spalte, wenn das Dataset auf eine einzelne Spalte aufgeteilt wird. Dies führt zu Echtzeitantworten auf alle weiteren Filteraufrufe in dieser Spalte.

Datensatz aktualisieren

Das Hinzufügen einer neuen Spalte durch Referenz wird mit dem Operator := durchgeführt, der eine Variable dem Dataset an Ort und Stelle zuweist. Dadurch wird eine In-Memory-Kopie des Datensatzes vermieden, sodass wir nicht jeder neuen Variablen Ergebnisse zuweisen müssen.

 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

Um mehr Variablen auf einmal hinzuzufügen, können wir die Syntax DT[, := (sum_delay = arr_delay + dep_delay)] , ähnlich wie .(sum_delay = arr_delay + dep_delay) beim Abfragen aus dem Datensatz.

Es ist möglich, durch Verweis Unterzuweisungen vorzunehmen, wobei nur bestimmte Zeilen an Ort und Stelle aktualisiert werden, indem einfach mit dem Argument i kombiniert wird.

 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

Daten sammeln

Um Daten zu aggregieren, stellen wir das dritte Argument by die eckige Klammer. Dann müssen wir in j aggregierte Funktionsaufrufe bereitstellen, damit die Daten tatsächlich aggregiert werden können. Das im Argument j verwendete Symbol .N entspricht der Anzahl aller Beobachtungen in jeder Gruppe. Wie bereits erwähnt, können Aggregate mit Teilmengen auf Zeilen und Auswahlspalten kombiniert werden.

 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

Oft müssen wir einen Wert einer Zeile mit seinem Aggregat über eine Gruppe vergleichen. In SQL wenden wir Aggregate über die Partition an durch : 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

Wenn wir Daten nicht mit diesen Aggregaten abfragen und sie stattdessen einfach per Referenz in die tatsächliche Tabellenaktualisierung einfügen möchten, können wir dies mit dem Operator := erreichen. Dadurch wird die In-Memory-Kopie des Datensatzes vermieden, sodass wir der neuen Variablen keine Ergebnisse zuweisen müssen.

 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

Datensätzen beitreten

Das Verbinden und Zusammenführen von Datensätzen mit Basis R wird als spezielle Art von Teilmengenoperationen betrachtet. Wir stellen einen Datensatz bereit, mit dem wir das erste eckige Klammerargument i verbinden möchten. Für jede Zeile im Dataset, die i bereitgestellt wird, gleichen wir Zeilen aus dem Dataset ab, in dem wir [ verwenden. Wenn wir nur übereinstimmende Zeilen behalten wollen ( Inner Join ), übergeben wir ein zusätzliches Argument nomatch = 0L . Wir verwenden das Argument on , um Spalten anzugeben, für die wir beide Datensätze zusammenführen möchten.

 # 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

Beachten Sie, dass der äußere Join aufgrund der Konsistenz mit der Basis-R-Untergruppe standardmäßig RIGHT OUTER ist. Wenn wir nach LEFT OUTER , müssen wir die Tabellen vertauschen, wie im obigen Beispiel. Das genaue Verhalten kann auch einfach in der Methode merge data.table gesteuert werden, indem dieselbe API verwendet wird wie base R merge data.frame .

Wenn wir einfach die Spalte(n) in unserem Datensatz nachschlagen möchten, können wir dies effizient mit dem Operator := im j Argument beim Verbinden tun. Genauso wie bei der Unterzuweisung per Referenz, wie im Abschnitt Datensatz aktualisieren beschrieben, fügen wir jetzt einfach eine Spalte per Referenz aus dem Datensatz hinzu, mit dem wir uns verbinden. Dadurch wird die In-Memory-Kopie von Daten vermieden, sodass wir keine Ergebnisse neuen Variablen zuweisen müssen.

 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

Verwenden Sie für Aggregat While Join by = .EACHI . Es führt Joins durch, die keine Zwischenergebnisse des Joins materialisieren, und wendet Aggregate im laufenden Betrieb an, wodurch es speichereffizient wird.

Rolling Join ist eine ungewöhnliche Funktion, die für den Umgang mit geordneten Daten entwickelt wurde. Es eignet sich perfekt für die Verarbeitung von Zeitdaten und Zeitreihen im Allgemeinen. Im Grunde werden Übereinstimmungen in der Join-Bedingung zum nächsten übereinstimmenden Wert gerollt. Verwenden Sie es, indem Sie beim Verbinden das roll Argument angeben.

Fast Overlap Join verbindet Datensätze auf der Grundlage von Perioden und der Handhabung von Überlappungen mithilfe verschiedener überlappender Operatoren: any , within , start , end .

Eine Non-Equi-Join- Funktion zum Verbinden von Datensätzen mit ungleichen Bedingungen wird derzeit entwickelt.

Profildaten

Beim Durchsuchen unseres Datensatzes möchten wir möglicherweise manchmal technische Informationen zu diesem Thema sammeln, um die Qualität der Daten besser zu verstehen.

Beschreibende Statistik

 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

Kardinalität

Wir können die Eindeutigkeit von Daten überprüfen, indem wir die uniqueN Funktion verwenden und sie auf jede Spalte anwenden. Das Objekt .SD in der Abfrage unten entspricht dem Subset der Data.table :

 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

NA-Verhältnis

Um das Verhältnis unbekannter Werte ( NA in R und NULL in SQL) für jede Spalte zu berechnen, stellen wir die gewünschte Funktion bereit, die auf jede Spalte angewendet werden soll.

 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

Daten exportieren

Der schnelle Export von Tabellendaten in das CSV -Format wird auch vom Paket data.table bereitgestellt.

 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

Zum Zeitpunkt der Erstellung dieses Artikels wurde die fwrite Funktion noch nicht im CRAN-Repository veröffentlicht. Um es zu verwenden, müssen wir die data.table Entwicklungsversion installieren, andernfalls können wir die Basis-R write.csv Funktion verwenden, aber erwarten Sie nicht, dass es schnell ist.

Ressourcen

Es stehen viele Ressourcen zur Verfügung. Neben den Handbüchern, die für jede Funktion verfügbar sind, gibt es auch Paketvignetten, das sind Tutorials, die sich auf das jeweilige Thema konzentrieren. Diese finden Sie auf der Seite Erste Schritte. Darüber hinaus listet die Präsentationsseite mehr als 30 Materialien (Folien, Videos usw.) von data.table Präsentationen auf der ganzen Welt auf. Auch die Community-Unterstützung ist im Laufe der Jahre gewachsen und hat kürzlich die 4000. Frage zum Tag Stack Overflow data.table erreicht, wobei immer noch ein hoher Anteil (91,9 %) an beantworteten Fragen vorliegt. Das folgende Diagramm zeigt die Anzahl der mit data.table getaggten Fragen zu Stack Overflow im Laufe der Zeit.

SO-Fragen monatlich für data.table – Nur Fragen mit data.table-Tags, keine mit data.table (akzeptierten) Antworten

SO-Fragen monatlich für data.table – Nur Fragen mit data.table-Tags, keine mit data.table (akzeptierten) Antworten

Zusammenfassung

Dieser Artikel enthält ausgewählte Beispiele für eine effiziente tabellarische Datentransformation in R mithilfe des data.table -Pakets. Die tatsächlichen Zahlen zur Leistung können durch die Suche nach reproduzierbaren Benchmarks überprüft werden. Ich habe einen zusammengefassten Blog-Beitrag über data.table Lösungen für die 50 am besten bewerteten StackOverflow-Fragen für die Sprache R mit dem Titel Solve common R problems efficiency with data.table veröffentlicht, in dem Sie viele Abbildungen und reproduzierbaren Code finden. Das Paket data.table verwendet die native Implementierung der schnellen Radix-Ordnung für seine Gruppierungsoperationen und die binäre Suche nach schnellen Teilmengen/Joins. Diese Radix-Reihenfolge wurde in Base R ab Version 3.3.0 integriert. Darüber hinaus wurde der Algorithmus kürzlich in die H2O-Plattform für maschinelles Lernen implementiert und über den H2O-Cluster parallelisiert, wodurch effiziente Big Joins in 10B x 10B-Zeilen ermöglicht werden.

Verwandte: Ultimative In-Memory-Datenerfassungsmanipulation mit Supergroup.js