Suche…


Einführung

Data.table ist ein Paket, das die Funktionalität von Datenrahmen von der Basis R aus erweitert und insbesondere deren Leistung und Syntax verbessert. Weitere Informationen finden Sie im Docs-Bereich des Pakets unter Erste Schritte mit data.table .

Syntax

  • DT[i, j, by]
    # DT [wo, wählen Sie | update | do, by]
  • DT[...][...]
    # ketten
  • ################# Shortcuts, special functions and special symbols inside DT[...]
  • ()
    # in mehreren Argumenten ersetzt list ()
  • J ()
    # in i ersetzt list ()
  • : =
    # in j, eine Funktion zum Hinzufügen oder Ändern von Spalten
  • .N
    # in i die Gesamtzahl der Zeilen
    # in j die Anzahl der Zeilen in einer Gruppe
  • .ICH
    # in j der Vektor der Zeilennummern in der Tabelle (gefiltert nach i)
  • .SD
    # in j, die aktuelle Untermenge der Daten
    # ausgewählt durch das Argument .SDcols
  • .GRP
    # in j der aktuelle Index der Untermenge der Daten
  • .DURCH
    # in j die Liste der by-Werte für die aktuelle Datenuntermenge
  • V1, V2, ...
    # Standardnamen für nicht benannte Spalten, die in j erstellt wurden
  • ################# Joins inside DT[...]
  • DT1 [DT2, Ein, J]
    # zwei Tische verbinden
  • ich.*
    # Sonderpräfix für DT2-Spalten nach dem Join
  • von = .EACHI
    # spezielle Option nur mit einem Join verfügbar
  • DT1 [! DT2, Ein, J]
    # Anti-Join von zwei Tabellen
  • DT1 [DT2, ein, rollen, j]
    # Verbinden Sie zwei Tabellen und rollen Sie in der letzten Spalte von on =
  • ################# Reshaping, stacking and splitting
  • Schmelze (DT, id.vars, measure.vars)
    # in langes Format umwandeln
    # Für mehrere Spalten verwenden Sie measure.vars = pattern (...).
  • dcast (DT, Formel)
    # in ein Breitformat umwandeln
  • rbind (DT1, DT2, ...)
    # Stack aufgezählte data.tables
  • rbindlist (DT_list, idcol)
    # stapeln Sie eine Liste von data.tables
  • Split (DT, von)
    # eine Datentabelle in eine Liste aufteilen
  • ################# Some other functions specialized for data.tables
  • Foverlaps
    # Überlappungen
  • verschmelzen
    # eine andere Möglichkeit, zwei Tabellen zu verbinden
  • einstellen
    # eine andere Möglichkeit, Spalten hinzuzufügen oder zu ändern
  • fintersect, fsetdiff, funion, fsetequal, einzigartig, dupliziert, anyDuplicated
    # Mengenoperationsoperationen mit Zeilen als Elementen
  • uniqueN
    Anzahl der verschiedenen Zeilen
  • rowidv (DT, Spalten)
    # Zeilen-ID (1 bis .N) innerhalb jeder Gruppe, bestimmt durch Spalten
  • rleidv (DT, cols)
    # Gruppen-ID (1 bis .GRP) innerhalb jeder Gruppe, bestimmt durch Anzahl von Spalten
  • Verschiebung (DT, n, Typ = c ("Lag", "Lead"))
    # Einen Schichtoperator auf jede Spalte anwenden
  • setorder, setcolorder, setnames, setkey, setindex, setattr
    # Attribute und Reihenfolge nach Verweis ändern

Bemerkungen

Installation und Unterstützung

So installieren Sie das Paket "data.table":

# install from CRAN
install.packages("data.table")       

# or install development version 
install.packages("data.table", type = "source", repos = "http://Rdatatable.github.io/data.table")

# and to revert from devel to CRAN, the current version must first be removed
remove.packages("data.table")
install.packages("data.table")

Auf der offiziellen Website des Pakets finden Sie Wiki-Seiten, die Ihnen den Einstieg erleichtern, sowie Listen mit Präsentationen und Artikeln aus dem Internet. Bevor Sie eine Frage stellen - hier bei StackOverflow oder anderswo - lesen Sie bitte die Support-Seite .

Paket laden

Viele der Funktionen in den obigen Beispielen sind im Namespace data.table enthalten. Um sie zu verwenden, müssen Sie zuerst eine Zeile wie die library(data.table) hinzufügen oder ihren vollständigen Pfad verwenden, beispielsweise data.table::fread anstatt nur fread . Für Hilfe zu den einzelnen Funktionen ist die Syntax - help("fread") oder ?fread . Wenn das Paket nicht geladen ist, verwenden Sie erneut den vollständigen Namen wie ?data.table::fread .

Eine Datentabelle anlegen

Eine data.table ist eine erweiterte Version der data.frame-Klasse von Basis R. Das class() -Attribut ist daher der Vektor "data.table" "data.frame" Funktionen, die auch auf einem data.frame funktionieren, werden verwendet Arbeit mit einer Datentabelle. Es gibt viele Möglichkeiten, eine data.table zu erstellen, zu laden oder zu zwingen.

Bauen

Vergessen Sie nicht, das Paket data.table zu installieren und zu aktivieren

library(data.table)

Es gibt einen Konstruktor mit demselben Namen:

DT <- data.table(
  x = letters[1:5], 
  y = 1:5, 
  z = (1:5) > 3
)
#    x y     z
# 1: a 1 FALSE
# 2: b 2 FALSE
# 3: c 3 FALSE
# 4: d 4  TRUE
# 5: e 5  TRUE

Im Gegensatz zu data.frame data.table data.frame data.table nicht zu Faktoren:

sapply(DT, class)
#               x           y           z 
#     "character"   "integer"   "logical" 

Einlesen

Wir können aus einer Textdatei lesen:

dt <- fread("my_file.csv")

Im read.csv fread liest fread Strings als Strings und nicht als Faktoren.

Ändern Sie einen Datenrahmen

Aus Gründen der Effizienz bietet data.table eine Möglichkeit, ein data.frame oder eine Liste zu ändern, um eine data.table an Ort und Stelle zu machen (ohne eine Kopie zu erstellen oder den Speicherort zu ändern):

# example data.frame
DF <- data.frame(x = letters[1:5], y = 1:5, z = (1:5) > 3)
# modification
setDT(DF)

Beachten Sie, dass wir das Ergebnis nicht <- zuweisen, da das Objekt DF vor Ort geändert wurde. Die Klassenattribute des data.frame bleiben erhalten:

sapply(DF, class)
#         x         y         z 
#  "factor" "integer" "logical" 

Erzwingen Sie ein Objekt in data.table

Wenn Sie über eine list , einen data.frame oder eine data.table , sollten Sie die Funktion setDT zum Konvertieren in eine data.table da sie die Konvertierung nach Verweis as.data.table anstatt eine Kopie zu as.data.table (wie as.data.table ). Dies ist wichtig, wenn Sie mit großen Datensätzen arbeiten.

Wenn Sie ein anderes R-Objekt haben (z. B. eine Matrix), müssen Sie as.data.table , um es in eine data.table .

mat <- matrix(0, ncol = 10, nrow = 10)

DT <- as.data.table(mat)
# or
DT <- data.table(mat)

Spalten hinzufügen und ändern

DT[where, select|update|do, by] Syntax wird verwendet, um mit Spalten einer data.table zu arbeiten.

  • "Wo" ist das i Argument
  • Der Teil "select | update | do" ist das Argument j

Diese beiden Argumente werden normalerweise nach Position statt nach Name übergeben.

Unsere Beispieldaten sind unten

mtcars = data.table(mtcars, keep.rownames = TRUE)

Ganze Spalten bearbeiten

Verwenden Sie den Operator := in j , um neue Spalten zuzuweisen:

mtcars[, mpg_sq := mpg^2]

Spalten entfernen, indem Sie NULL :

mtcars[, mpg_sq := NULL]

Fügen Sie mehrere Spalten hinzu, indem Sie das multivariate Format des Operators := verwenden:

mtcars[, `:=`(mpg_sq = mpg^2, wt_sqrt = sqrt(wt))]
# or 
mtcars[, c("mpg_sq", "wt_sqrt") := .(mpg^2, sqrt(wt))]

Wenn die Spalten abhängig sind und nacheinander definiert werden müssen, gibt es eine Möglichkeit:

mtcars[, c("mpg_sq", "mpg2_hp") := .(temp1 <- mpg^2, temp1/hp)]

Die Syntax .() Wird verwendet, wenn die rechte Seite von LHS := RHS eine Liste von Spalten ist.

Verwenden Sie für dynamisch bestimmte Spaltennamen Klammern:

vn = "mpg_sq"
mtcars[, (vn) := mpg^2]

Spalten können auch mit set geändert werden, obwohl dies selten notwendig ist:

set(mtcars, j = "hp_over_wt", v = mtcars$hp/mtcars$wt)

Untermengen von Spalten bearbeiten

Verwenden Sie das Argument " i , um die Zeilen in den Untermengen zu sortieren, in denen "Änderungen" vorgenommen werden sollen:

mtcars[1:3, newvar := "Hello"]
# or
set(mtcars, j = "newvar", i = 1:3, v = "Hello")  

Wie in einem data.frame können wir eine Teilmenge mit Zeilennummern oder logischen Tests vornehmen. Es ist auch möglich, einen "Join" in i , die kompliziertere Aufgabe wird jedoch in einem anderen Beispiel behandelt.

Spaltenattribute bearbeiten

Funktionen, die Attribute bearbeiten, z. B. levels<- oder names<- , ersetzen ein Objekt tatsächlich durch eine modifizierte Kopie. Auch wenn nur eine Spalte in einer Datentabelle verwendet wird, wird das gesamte Objekt kopiert und ersetzt.

Um ein Objekt ohne Kopien zu ändern, verwenden Sie setnames , um die Spaltennamen von data.table oder data.frame und setattr zu ändern, um ein Attribut für ein beliebiges Objekt zu ändern.

# Print a message to the console whenever the data.table is copied
tracemem(mtcars)
mtcars[, cyl2 := factor(cyl)]

# Neither of these statements copy the data.table
setnames(mtcars, old = "cyl2", new = "cyl_fac")
setattr(mtcars$cyl_fac, "levels", c("four", "six", "eight"))

# Each of these statements copies the data.table
names(mtcars)[names(mtcars) == "cyl_fac"] <- "cf"
levels(mtcars$cf) <- c("IV", "VI", "VIII")

Beachten Sie, dass diese Änderungen durch Verweis vorgenommen werden, sodass sie global sind . Wenn Sie sie innerhalb einer Umgebung ändern, wirkt sich dies auf das Objekt in allen Umgebungen aus.

# This function also changes the levels in the global environment
edit_levels <- function(x) setattr(x, "levels", c("low", "med", "high"))
edit_levels(mtcars$cyl_factor)

Spezielle Symbole in data.table

.SD

.SD bezieht sich auf die Teilmenge der data.table für jede Gruppe, ausgenommen alle Spalten, die in verwendet by .

.SD zusammen mit lapply verwendet werden, um jede Funktion auf mehrere Spalten nach Gruppe in einer data.table

Wir werden weiterhin dasselbe eingebaute Dataset, mtcars :

mtcars = data.table(mtcars) # Let's not include rownames to keep things simpler

Mittelwert aller Spalten im Datensatz nach Zylinderanzahl , cyl :

mtcars[ , lapply(.SD, mean), by = cyl]

#   cyl      mpg     disp        hp     drat       wt     qsec        vs        am     gear     carb
#1:   6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 3.428571
#2:   4 26.66364 105.1364  82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 1.545455
#3:   8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 3.500000

Neben cyl gibt es im Datensatz weitere Kategoriespalten wie vs , am , gear und carb . Es macht keinen Sinn, den mean dieser Spalten zu nehmen. Lassen Sie uns diese Spalten ausschließen. Hier kommt das .SDcols ins .SDcols .

.Scols

.SDcols gibt die Spalten der data.table , die in .SD .

Mittel aller Spalten (continuous Spalten) in der Datenmenge durch die Anzahl der Zahnräder gear und die Anzahl der Zylinder, cyl , angeordnet durch gear und cyl :

# All the continuous variables in the dataset
cols_chosen <- c("mpg", "disp", "hp", "drat", "wt", "qsec")

mtcars[order(gear, cyl), lapply(.SD, mean), by = .(gear, cyl), .SDcols = cols_chosen]

#   gear cyl    mpg     disp       hp     drat       wt    qsec
#1:    3   4 21.500 120.1000  97.0000 3.700000 2.465000 20.0100
#2:    3   6 19.750 241.5000 107.5000 2.920000 3.337500 19.8300
#3:    3   8 15.050 357.6167 194.1667 3.120833 4.104083 17.1425
#4:    4   4 26.925 102.6250  76.0000 4.110000 2.378125 19.6125
#5:    4   6 19.750 163.8000 116.5000 3.910000 3.093750 17.6700
#6:    5   4 28.200 107.7000 102.0000 4.100000 1.826500 16.8000
#7:    5   6 19.700 145.0000 175.0000 3.620000 2.770000 15.5000
#8:    5   8 15.400 326.0000 299.5000 3.880000 3.370000 14.5500

Vielleicht möchten wir den mean nach Gruppen berechnen. Um den Mittelwert für alle Autos im Datensatz zu berechnen, geben wir die by Variable nicht an.

mtcars[ , lapply(.SD, mean), .SDcols = cols_chosen] 

#        mpg     disp       hp     drat      wt     qsec
#1: 20.09062 230.7219 146.6875 3.596563 3.21725 17.84875

Hinweis:

  • Es ist nicht notwendig, vorher cols_chosen zu definieren. .SDcols können .SDcols direkt übernehmen
  • .SDcols können auch direkt einen Vektor von Spaltennummern aufnehmen. Im obigen Beispiel wäre dies mtcars[ , lapply(.SD, mean), .SDcols = c(1,3:7)]

.N

.N ist die Abkürzung für die Anzahl der Zeilen in einer Gruppe.

iris[, .(count=.N), by=Species]

#      Species count
#1:     setosa    50
#2: versicolor    50
#3:  virginica    50

Code schreiben, der mit data.frame und data.table kompatibel ist

Unterschiede in der Subsetting-Syntax

A data.table ist eines von mehreren zweidimensionalen Datenstrukturen in R neben data.frame , matrix und (2D) array . Alle diese Klassen verwenden eine sehr ähnliche, jedoch nicht identische Syntax für das Subsetting, das Schema A[rows, cols] .

Betrachten Sie die folgenden Daten, die in einer matrix , einem data.frame und einer data.table :

ma <- matrix(rnorm(12), nrow=4, dimnames=list(letters[1:4], c('X', 'Y', 'Z')))
df <- as.data.frame(ma)
dt <- as.data.table(ma)

ma[2:3]  #---> returns the 2nd and 3rd items, as if 'ma' were a vector (because it is!)
df[2:3]  #---> returns the 2nd and 3rd columns
dt[2:3]  #---> returns the 2nd and 3rd rows!

Wenn Sie sicher sein möchten, was zurückgegeben wird, ist es besser, explizit zu sein .

Um bestimmte Zeilen zu erhalten , fügen Sie nach dem Bereich ein Komma hinzu:

ma[2:3, ]  # \
df[2:3, ]  #  }---> returns the 2nd and 3rd rows
dt[2:3, ]  # /

Wenn Sie jedoch Teilmengen von Spalten erstellen möchten, werden einige Fälle unterschiedlich interpretiert. Alle drei können auf dieselbe Weise Teilmengen mit Ganzzahlen- oder Zeichenindizes sein, die nicht in einer Variablen gespeichert sind.

ma[, 2:3]          #  \
df[, 2:3]          #   \
dt[, 2:3]          #    }---> returns the 2nd and 3rd columns
ma[, c("Y", "Z")]  #   /
df[, c("Y", "Z")]  #  /
dt[, c("Y", "Z")]  # /

Sie unterscheiden sich jedoch für nicht benannte Variablennamen

mycols <- 2:3
ma[, mycols]                # \
df[, mycols]                #  }---> returns the 2nd and 3rd columns
dt[, mycols, with = FALSE]  # /

dt[, mycols]                # ---> Raises an error

Im letzten Fall wird mycols als Name einer Spalte ausgewertet. Da dt keine Spalte namens mycols , wird ein Fehler mycols .

Anmerkung: Bei Versionen des data.table Pakets vor 1.9.8 unterschied sich dieses Verhalten geringfügig. Alles, was sich im Spaltenindex befindet, wurde unter Verwendung von dt als Umgebung bewertet. Also würden sowohl dt[, 2:3] als auch dt[, mycols] den Vektor 2:3 . Für den zweiten Fall wird kein Fehler mycols , da die Variable mycols in der übergeordneten Umgebung vorhanden ist.

Strategien zur Aufrechterhaltung der Kompatibilität mit data.frame und data.table

Es gibt viele Gründe, Code zu schreiben, der garantiert mit data.frame und data.table . Möglicherweise müssen Sie data.frame , oder Sie müssen Code data.frame , der nicht weiß, wie er verwendet wird. Es gibt also einige Hauptstrategien, um dies in der Reihenfolge der Bequemlichkeit zu erreichen:

  1. Verwenden Sie eine Syntax, die für beide Klassen gleich ist.
  2. Verwenden Sie eine allgemeine Funktion, die dasselbe tut wie die kürzeste Syntax.
  3. data.table , dass data.table sich wie data.frame (Beispiel: Aufruf der spezifischen Methode print.data.frame ).
  4. Behandle sie als list , was sie letztendlich sind.
  5. Konvertieren Sie die Tabelle in einen data.frame bevor Sie etwas tun (schlechte Idee, wenn es sich um eine große Tabelle handelt).
  6. Konvertieren Sie die Tabelle in data.table , wenn Abhängigkeiten keine data.table .

Teilmengenzeilen Es ist einfach, verwenden Sie einfach die [, ] Auswahl mit dem Komma:

A[1:10, ]
A[A$var > 17, ]  # A[var > 17, ] just works for data.table

Teilmengenspalten Wenn Sie eine einzelne Spalte wünschen, verwenden Sie die $ oder [[ ]] :

A$var
colname <- 'var'
A[[colname]]
A[[1]]

Wenn Sie möchten, dass mehrere Spalten einheitlich erfasst werden, müssen Sie ein wenig ansprechen:

B <- `[.data.frame`(A, 2:4)

# We can give it a better name
select <- `[.data.frame`
B <- select(A, 2:4)
C <- select(A, c('foo', 'bar'))

Teilmenge 'indizierte' Zeilen Während data.frame hat row.names , data.table hat sein einzigartiges key Am besten vermeiden Sie row.names vollständig und nutzen die vorhandenen Optimierungen im Fall von data.table Möglichkeit.

B <- A[A$var != 0, ]
# or...
B <- with(A, A[var != 0, ])  # data.table will silently index A by var before subsetting

stuff <- c('a', 'c', 'f')
C <- A[match(stuff, A$name), ]  # really worse than: setkey(A); A[stuff, ]

Holen Sie sich eine 1-Spalten-Tabelle, erhalten Sie eine Zeile als Vektor. Das ist einfach mit dem, was wir bisher gesehen haben:

B <- select(A, 2)    #---> a table with just the second column
C <- unlist(A[1, ])  #---> the first row as a vector (coerced if necessary)

Schlüssel in data.table setzen

Ja, Sie müssen SETKEY vor 1.9.6 einstellen

In der Vergangenheit (vor 1.9.6) wurde Ihre data.table beschleunigt, indem Sie Spalten als Schlüssel für die Tabelle data.table , insbesondere für große Tabellen. [Siehe Intro-Vignette Seite 5 der Version von September 2015, bei der die Suchgeschwindigkeit 544-mal besser war.] Möglicherweise finden Sie älteren Code, der diese Einstellungstasten mit 'setkey' verwendet oder beim Einrichten der Tabelle eine Spalte 'key =' setzt.

library(data.table)
DT <- data.table(
  x = letters[1:5], 
  y = 5:1, 
  z = (1:5) > 3
)

#> DT
#   x y     z
#1: a 5 FALSE
#2: b 4 FALSE
#3: c 3 FALSE
#4: d 2  TRUE
#5: e 1  TRUE

setkey Sie Ihren Schlüssel mit dem Befehl setkey . Sie können einen Schlüssel mit mehreren Spalten haben.

setkey(DT, y)

Überprüfen Sie den Schlüssel Ihrer Tabelle in Tabellen ()

tables()

> tables()
     NAME NROW NCOL MB COLS  KEY
[1,] DT      5    3  1 x,y,z y  
Total: 1MB

Beachten Sie, dass dadurch Ihre Daten neu sortiert werden.

#> DT
#   x y     z
#1: e 1  TRUE
#2: d 2  TRUE
#3: c 3 FALSE
#4: b 4 FALSE
#5: a 5 FALSE

Jetzt ist es unnötig

Vor v1.9.6 mussten Sie für bestimmte Operationen einen Schlüssel festgelegt haben, insbesondere das Verbinden von Tabellen. Die Entwickler von data.table haben eine "on=" -Funktion eingeführt, die die Abhängigkeit von Schlüsseln ersetzen kann. Siehe SO-Antwort hier für eine ausführliche Diskussion.

Im Januar 2017 haben die Entwickler eine Vignette um Sekundärindizes geschrieben, die die "Ein" -Syntax erläutert und die Identifizierung anderer Spalten für eine schnelle Indizierung ermöglicht.

Sekundärindizes erstellen?

In ähnlicher Weise wie key können Sie setindex(DT, key.col) oder setindexv(DT, "key.col.string") , wobei DT Ihre data.table ist. Entfernen Sie alle Indizes mit setindex(DT, NULL) .

Sehen Sie Ihre Sekundärindizes mit indices(DT) .

Warum Sekundärindizes?

Dies sortiert die Tabelle nicht (im Gegensatz zu key), ermöglicht jedoch eine schnelle Indizierung mit der "on" -Syntax. Beachten Sie, dass es nur einen Schlüssel geben kann. Sie können jedoch mehrere sekundäre Indizes verwenden, sodass Sie die Tabelle nicht erneut eingeben und neu sortieren müssen. Dadurch wird Ihr Subsetting beschleunigt, wenn Sie die Spalten ändern, für die Sie einen Subset erstellen möchten.

Erinnern Sie sich, im obigen Beispiel war y der Schlüssel für die Tabelle DT:

DT
# x y     z
# 1: e 1  TRUE
# 2: d 2  TRUE
# 3: c 3 FALSE
# 4: b 4 FALSE
# 5: a 5 FALSE

# Let us set x as index 
setindex(DT, x)

# Use indices to see what has been set
indices(DT)
# [1] "x"

# fast subset using index and not keyed column
DT["c", on ="x"]
#x y     z
#1: c 3 FALSE

# old way would have been rekeying DT from y to x, doing subset and 
# perhaps keying back to y (now we save two sorts)
# This is a toy example above but would have been more valuable with big data sets


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow