R data.table Symbole und Operatoren, die Sie kennen sollten

Der Code von R data.table wird effizienter und eleganter, wenn Sie die speziellen Symbole und Funktionen nutzen. In diesem Sinne werden wir uns einige spezielle Möglichkeiten ansehen, um neue Spalten zu unterteilen, zu zählen und neue Spalten zu erstellen.

Für diese Demo werde ich Daten aus der Entwicklerumfrage von Stack Overflow 2019 mit etwa 90.000 Antworten verwenden. Wenn Sie mitmachen möchten, können Sie die Daten von Stack Overflow herunterladen.

Wenn das Paket data.table nicht auf Ihrem System installiert ist, installieren Sie es von CRAN und laden Sie es dann wie gewohnt mit library(data.table). Zu Beginn möchten Sie möglicherweise nur die ersten Zeilen des Datensatzes einlesen, um die Überprüfung der Datenstruktur zu vereinfachen. Sie können dies mit der fread()Funktion von data.table und dem nrowsArgument tun . Ich werde in 10 Zeilen lesen:

data_sample <- fread ("data / query_results_public.csv", nrows = 10)

Wie Sie sehen werden, müssen 85 Spalten untersucht werden. (Wenn Sie wissen möchten, was alle Spalten bedeuten, enthält der Download Dateien mit dem Datenschema und einem PDF der ursprünglichen Umfrage.) 

Um alle Daten einzulesen, verwende ich:

mydt <- fread ("data / query_results_public.csv")

Als Nächstes erstelle ich eine neue Datentabelle mit nur wenigen Spalten, um die Arbeit mit und das Anzeigen von Ergebnissen zu vereinfachen. Eine Erinnerung daran, dass data.table diese grundlegende Syntax verwendet: 

mydt [i, j, von]

In der Einführung in das Paket data.table heißt es: "Nehmen Sie dt-, Teilmengen- oder Neuordnungszeilen mit i, berechnen Sie j, gruppiert nach." Beachten Sie, dass i und j der Klammerreihenfolge von Basis R ähnlich sind: Zeilen zuerst, Spalten zweitens. Ich bin also für Operationen, die Sie für Zeilen ausführen würden (Auswahl von Zeilen basierend auf Zeilennummern oder Bedingungen); j ist das, was Sie mit Spalten tun würden (Spalten auswählen oder neue Spalten aus Berechnungen erstellen). Beachten Sie jedoch auch, dass Sie in data.table-Klammern viel mehr tun können als in einem Basis-R-Datenrahmen. Und der Abschnitt "by" ist neu in data.table.

Da ich Spalten auswähle , steht dieser Code an der Stelle "j", was bedeutet, dass die Klammern zuerst ein Komma benötigen, um die Stelle "i" leer zu lassen:

mydt [, j]

Wählen Sie die Spalten data.table aus

Eines der Dinge, die ich an data.table mag, ist, dass es einfach ist, Spalten in Anführungszeichen oder ohne Anführungszeichen auszuwählen . Nicht zitiert ist oft bequemer (das ist normalerweise der richtige Weg). Aber zitierte ist nützlich , wenn Sie data.table in Ihren eigenen Funktionen sind, oder wenn Sie wollen in einem Vektor passieren Sie woanders in Ihrem Code erstellt.

Sie können data.table-Spalten auf die typische Basis-R-Weise mit einem herkömmlichen Vektor aus Spaltennamen in Anführungszeichen auswählen. Zum Beispiel: 

dt1 <- mydt [, c ("LanguageWorkedWith", "LanguageDesireNextYear",

"OpenSourcer", "CurrencySymbol", "ConvertedComp",

"Hobbyist")]

Wenn Sie sie verwenden möchten un zitiert, erstellen Sie eine Liste anstelle eines Vektors und Sie können in den nicht notierten Namen übergeben. 

dt1 <- mydt [, list (LanguageWorkedWith, LanguageDesireNextYear,

OpenSourcer, CurrencySymbol, ConvertedComp,

Hobbyist)]

Und jetzt kommen wir zu unserem ersten besonderen Symbol. Anstatt zu tippen, list()können Sie einfach einen Punkt verwenden:

dt1 <- mydt [,. (LanguageWorkedWith, LanguageDesireNextYear,

OpenSourcer, CurrencySymbol, ConvertedComp,

Hobbyist)]

Das .()ist eine Abkürzung für list()innen data.table Klammern.

Was ist, wenn Sie einen bereits vorhandenen Vektor mit Spaltennamen verwenden möchten? Das Einfügen des Vektorobjektnamens in data.table-Klammern funktioniert nicht. Wenn ich einen Vektor mit zitierten Spaltennamen erstelle, wie folgt: 

mycols <- c ("LanguageWorkedWith", "LanguageDesireNextYear",

"OpenSourcer", "CurrencySymbol", "ConvertedComp", "Hobbyist")

Dann funktioniert dieser Code  nicht

dt1 <- mydt [, mycols]

Stattdessen müssen Sie .. (das sind zwei Punkte) vor den Namen des Vektorobjekts setzen:

dt1 <- mydt [, ..mycols]

Warum zwei Punkte? Das kam mir irgendwie zufällig vor, bis ich die Erklärung las. Stellen Sie sich das wie die zwei Punkte in einem Unix-Befehlszeilenterminal vor, die Sie in ein Verzeichnis verschieben. Hier verschieben Sie einen Namespace von der Umgebung in den Klammern von data.table bis zur globalen Umgebung. (Das hilft mir wirklich, mich daran zu erinnern!)

Zählen Sie die Zeilen der Datentabelle

Weiter zum nächsten Symbol. Um nach Gruppen zu zählen, können Sie das .NSymbol von data.table verwenden , wobei  .N"Anzahl der Zeilen" steht. Dies kann die Gesamtzahl der Zeilen oder die Anzahl der Zeilen pro Gruppe sein, wenn Sie im Abschnitt " Nach " aggregieren. 

Dieser Ausdruck gibt die Gesamtzahl der Zeilen in der data.table zurück: 

mydt [, .N]

Das folgende Beispiel berechnet die Anzahl der Zeilen, die nach einer Variablen gruppiert sind: Gibt an, ob Personen in der Umfrage auch als Hobby (die HobbyistVariable) codieren .

mydt [, .N, Hobbyist]

# kehrt zurück:

Hobbyist N 1: Ja 71257 2: Nein 17626

Sie können den einfachen Spaltennamen in Klammern in data.table verwenden, wenn nur eine Variable vorhanden ist. Wenn Sie nach zwei oder mehr Variablen gruppieren möchten, verwenden Sie das .Symbol. Zum Beispiel:

mydt [, .N ,. (Hobbyist, OpenSourcer)]

Um die Ergebnisse vom höchsten zum niedrigsten zu ordnen, können Sie nach dem ersten einen zweiten Satz Klammern hinzufügen. Das .NSymbol generiert automatisch eine Spalte mit dem Namen N (natürlich können Sie sie bei Bedarf umbenennen), sodass die Reihenfolge nach der Anzahl der Zeilen ungefähr so ​​aussehen kann:

mydt [, .N ,. (Hobbyist, OpenSourcer)] [Bestellung (Hobbyist, -N)]

Wenn ich data.table-Code lerne, finde ich es hilfreich, ihn Schritt für Schritt zu lesen. Also las ich dies als "Für alle Zeilen in mydt (da sich nichts im" Ich "-Spot befindet), zähle die Anzahl der Zeilen, gruppiert nach Hobbyist und OpenSourcer. Dann zuerst nach Hobbyist bestellen und dann die Anzahl der absteigenden Reihen. “ 

Das entspricht diesem dplyr-Code:

mydf%>%

count (Hobbyist, OpenSourcer)%>%

bestellen (Hobbyist, -n)

Wenn Sie den tidyverse konventionellen mehrzeiligen Ansatz besser lesbar finden, funktioniert dieser data.table-Code auch:

mydt [, .N,

(Hobbyist, OpenSourcer)] [

bestellen (Hobbyist, -N)

]]

Hinzufügen von Spalten zu einer data.table

Als nächstes möchte ich Spalten hinzufügen, um zu sehen, ob jeder Befragte R verwendet, ob er Python verwendet, ob er beide verwendet oder ob er keine verwendet. Die LanguageWorkedWithSpalte enthält Informationen zu den verwendeten Sprachen. Einige Zeilen dieser Daten sehen folgendermaßen aus:

Sharon Machlis

Jede Antwort ist eine einzelne Zeichenfolge. Die meisten haben mehrere Sprachen, die durch ein Semikolon getrennt sind.

Wie so oft ist es einfacher, nach Python zu suchen als nach R, da Sie nicht einfach nach "R" in der Zeichenfolge suchen können (Ruby und Rust enthalten auch ein großes R), wie Sie nach "Python" suchen können. Dies ist der einfachere Code zum Erstellen eines TRUE / FALSE-Vektors, der prüft, ob jeder String LanguageWorkedWithPython enthält:

ifelse (LanguageWorkedWith% like% "Python", TRUE, FALSE)

Wenn Sie SQL kennen, erkennen Sie diese "Gefällt mir" -Syntax. Ich mag, %like%. es ist eine schöne, optimierte Möglichkeit, nach Mustern zu suchen. In der Funktionsdokumentation heißt es, dass es in Klammern in data.table verwendet werden soll. Sie können es jedoch in jedem Code verwenden, nicht nur in data.tables. Ich habe mich bei Matt Dowle, dem Ersteller von data.table, erkundigt, der sagte, dass der Ratschlag, ihn in den Klammern zu verwenden, darin besteht, dass dort eine zusätzliche Leistungsoptimierung stattfindet.

Als nächstes folgt der Code zum Hinzufügen einer Spalte mit dem Namen PythonUser zur data.table:

dt1 [, PythonUser: = ifelse (LanguageWorkedWith% like% "Python", TRUE, FALSE)]

Beachten Sie den :=Bediener. Python hat auch einen solchen Operator, und seit ich gehört habe, dass er "Walross-Operator" heißt, nenne ich ihn so. Ich denke, es ist offiziell "Zuweisung durch Referenz". Dies liegt daran, dass der obige Code das vorhandene Objekt dt1 data.table durch Hinzufügen der neuen Spalte geändert hat - ohne dass es in einer neuen Variablen gespeichert werden muss .

Um nach R zu suchen, verwende ich den regulären Ausdruck "\\bR\\b": „Finde ein Muster, das mit einer Wortgrenze beginnt - die \\b, dann eine Rund dann mit einer anderen Wortgrenze. (Ich kann nicht einfach nach "R" suchen, da das letzte Element in jeder Zeichenfolge kein Semikolon enthält.) 

Dies fügt dt1 eine RUser-Spalte hinzu:

dt1 [, RUser: = ifelse (LanguageWorkedWith% like% "\\ bR \\ b", TRUE, FALSE)]

Wenn Sie beide Spalten gleichzeitig hinzufügen :=möchten, müssen Sie diesen Walross-Operator in eine Funktion verwandeln, indem Sie ihn wie folgt zurückzählen:

dt1 [, `: =` (

PythonUser = ifelse (LanguageWorkedWith% like% "Python", TRUE, FALSE),

RUser = ifelse (LanguageWorkedWith% like% "\\ bR \\ b", TRUE, FALSE)

)]

Weitere nützliche Operatoren für data.table

Es gibt mehrere andere wissenswerte data.table-Operatoren. Der  %between% Operator hat folgende Syntax:

myvector% zwischen% c (unterer_Wert, oberer_Wert)

Wenn ich also nach allen Antworten filtern möchte, bei denen die Entschädigung zwischen 50.000 und 100.000 US-Dollar betrug, funktioniert dieser Code:

comp_50_100k <- dt1 [CurrencySymbol == "USD" &

ConvertedComp% zwischen% c (50000, 100000)]

Die zweite Zeile oben ist die Zwischenbedingung. Beachten Sie, dass der %between%Operator bei der Prüfung sowohl den unteren als auch den oberen Wert berücksichtigt.

Ein weiterer nützlicher Operator ist %chin%. Es funktioniert wie Basis-Rs %in%, ist jedoch auf Geschwindigkeit optimiert und nur für Zeichenvektoren . Wenn ich also nach allen Zeilen filtern möchte, in denen die OpenSourcer-Spalte entweder "Nie" oder "Weniger als einmal pro Jahr" war, funktioniert dieser Code:

raros <- dt1 [OpenSourcer% chin% c ("Nie", "Weniger als einmal pro Jahr")]

Dies ist der Basis R ziemlich ähnlich, außer dass die Basis R den Datenrahmennamen in der Klammer angeben muss und nach dem Filterausdruck auch ein Komma benötigt:

raros_df <- df1 [df1 $ OpenSourcer% in% c ("Nie", "Weniger als einmal pro Jahr"),]

Die neue Funktion fcase ()

Für diese letzte Demo erstelle ich zunächst eine neue Datentabelle mit nur Personen, die eine Entschädigung in US-Dollar gemeldet haben:

usd <- dt1 [CurrencySymbol == "USD" &! is.na (ConvertedComp)]

Als nächstes werde ich eine neue Spalte erstellen, in der angegeben wird, Languageob jemand nur R, nur Python, beide oder keine verwendet. Und ich werde die neue fcase()Funktion verwenden. Zum Zeitpunkt der Veröffentlichung dieses Artikels war er fcase()nur in der Entwicklungsversion von data.table verfügbar. Wenn Sie data.table bereits installiert haben, können Sie mit diesem Befehl auf die neueste Entwicklungsversion aktualisieren: 

data.table :: update.dev.pkg ()

Die Funktion fcase () ähnelt der SQL- CASE WHENAnweisung und der case_when()Funktion von dplyr . Die grundlegende Syntax ist  fcase(condition1, "value1", condition2, "value2")und so weiter. Ein Standardwert für "alles andere" kann mit hinzugefügt werden default = value.

Hier ist Code zum Erstellen der neuen Sprachspalte:

usd [, Sprache: = fcase (

RUser &! PythonUser, "R",

PythonUser &! RUser, "Python",

PythonUser & RUser, "Both",

! PythonUser &! RUser, "Weder noch"

)]

Ich setze jede Bedingung in eine separate Zeile, weil ich es leichter zu lesen finde, aber Sie müssen nicht.

Achtung: Wenn Sie RStudio verwenden, wird die Struktur data.table im RStudio-Bereich oben rechts nicht automatisch aktualisiert, nachdem Sie mit dem Walross-Operator eine neue Spalte erstellt haben. Sie müssen manuell auf das Aktualisierungssymbol klicken, um Änderungen in der Anzahl der Spalten anzuzeigen.

Es gibt einige andere Symbole, die ich in diesem Artikel nicht behandeln werde. Eine Liste davon finden Sie in der Hilfedatei "Sonderzeichen" data.table, indem Sie ausführen help("special-symbols"). Eines der nützlichsten, .SD, hat bereits einen eigenen Do More With R-Artikel und ein eigenes Video mit dem Titel „Verwendung von .SD im R data.table-Paket“.

Weitere R-Tipps finden Sie auf der YouTube-Wiedergabeliste „Do More With R“ auf der Seite „Do More With R“.