Поиск…


Вступление

Data.table - это пакет, который расширяет функциональные возможности фреймов данных из базы R, особенно улучшая их производительность и синтаксис. Подробную информацию см. В разделе «Документы» пакета в разделе « Начало работы с data.table» .

Синтаксис

  • DT[i, j, by]
    # DT [где, выберите | update | do, by]
  • DT[...][...]
    # цепочка
  • ################# Shortcuts, special functions and special symbols inside DT[...]
  • . ()
    # в нескольких аргументах, заменяет список ()
  • J ()
    # in i, заменяет список ()
  • знак равно
    # in j, функция, используемая для добавления или изменения столбцов
  • .N
    # в i, общее количество строк
    # в j, количество строк в группе

  • # in j, вектор номеров строк в таблице (отфильтрованный i)
  • .sd
    # в j, текущее подмножество данных
    #, выбранный аргументом .SDcols
  • .grp
    # в j, текущий индекс подмножества данных
  • .ОТ
    # в j, список по значениям для текущего подмножества данных
  • V1, V2, ...
    # имена по умолчанию для неназванных столбцов, созданных в j
  • ################# Joins inside DT[...]
  • DT1 [DT2, on, j]
    # присоединиться к двум таблицам
  • я.*
    # специальный префикс на столбцах DT2 после объединения
  • от = .EACHI
    # специальный вариант доступен только с присоединением
  • DT1 [! DT2, on, j]
    # анти-объединение двух таблиц
  • DT1 [DT2, on, roll, j]
    # присоединиться к двум таблицам, перекатывая последний столбец в on =
  • ################# Reshaping, stacking and splitting
  • расплав (DT, id.vars, measure.vars)
    # преобразовать в длинный формат
    # для нескольких столбцов, используйте measure.vars = patterns (...)
  • dcast (DT, формула)
    # преобразовать в широкий формат
  • rbind (DT1, DT2, ...)
    # stack перечислены data.tables
  • rbindlist (DT_list, idcol)
    # стек список data.tables
  • split (DT, by)
    # разбить таблицу data.table в список
  • ################# Some other functions specialized for data.tables
  • foverlaps
    # перекрытие объединяется
  • сливаться
    # другой способ соединения двух таблиц
  • задавать
    # другой способ добавления или изменения столбцов
  • fintersect, fsetdiff, funion, fsetequal, уникальный, дублированный, anyDuplicated
    # операции теории множеств со строками как элементами
  • uniqueN
    # количество отдельных строк
  • rowidv (DT, cols)
    # row ID (от 1 до .N) в каждой группе, определяемой cols
  • rleidv (DT, cols)
    # идентификатор группы (от 1 до .GRP) в каждой группе, определяемый циклами cols
  • shift (DT, n, type = c ("lag", "lead"))
    # применить оператор сдвига к каждому столбцу
  • setorder, setcolorder, setnames, setkey, setindex, setattr
    # изменять атрибуты и порядок по ссылке

замечания

Установка и поддержка

Чтобы установить пакет 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")

На официальном сайте пакета есть страницы вики, которые помогают начать работу, а также списки презентаций и статей со всего Интернета. Прежде чем задавать вопрос - здесь, в StackOverflow или где-либо еще - прочитайте страницу поддержки .

Загрузка пакета

Многие функции в приведенных выше примерах существуют в пространстве имен data.table. Чтобы использовать их, вам нужно сначала добавить строку, такую ​​как library(data.table) или использовать полный путь, например data.table::fread а не просто fread . Для помощи по отдельным функциям синтаксис - это help("fread") или « ?fread . Опять же, если пакет не загружен, используйте полное имя типа ?data.table::fread .

Создание таблицы данных.

Data.table - это расширенная версия класса data.frame из базы R. Таким образом, атрибут class() представляет собой вектор "data.table" "data.frame" а функции, которые работают с data.frame, также будут работа с таблицей данных. Существует множество способов создания, загрузки или принуждения к таблице данных.

строить

Не забудьте установить и активировать пакет data.table

library(data.table)

Существует одноименный конструктор:

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

В отличие от data.frame , data.table не будет принуждать строки к факторам:

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

Читайте в

Мы можем читать из текстового файла:

dt <- fread("my_file.csv")

В отличие от read.csv , fread будет читать строки как строки, а не как факторы.

Измените файл data.frame

Для эффективности data.table предлагает способ изменения data.frame или списка, чтобы сделать data.table на месте (без копирования или изменения его памяти):

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

Обратите внимание, что мы не <- присваиваем результат, так как объект DF был изменен на месте. Атрибуты класса data.frame будут сохранены:

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

Объект принуждения к data.table

Если у вас есть list , data.frame или data.table , вы должны использовать функцию setDT для преобразования в data.table потому что она делает преобразование по ссылке вместо создания копии (что делает as.data.table ). Это важно, если вы работаете с большими наборами данных.

Если у вас есть другой объект R (такой как матрица), вы должны использовать as.data.table чтобы принудить его к data.table .

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

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

Добавление и изменение столбцов

DT[where, select|update|do, by] используется для работы с столбцами таблицы данных.

  • Часть «где» является аргументом i
  • Часть «select | update | do» является аргументом j

Эти два аргумента обычно передаются положением вместо имени.

Ниже приведены приведенные ниже примеры

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

Редактирование целых столбцов

Используйте оператор := внутри j для назначения новых столбцов:

mtcars[, mpg_sq := mpg^2]

Удалите столбцы, установив NULL :

mtcars[, mpg_sq := NULL]

Добавьте несколько столбцов, используя многомерный формат оператора := :

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

Если столбцы зависят и должны быть определены последовательно, один из способов:

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

Синтаксис .() Используется, когда правая часть LHS := RHS - это список столбцов.

Для динамически определяемых имен столбцов используйте круглые скобки:

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

Столбцы также могут быть изменены с помощью set , хотя это редко необходимо:

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

Редактирование подмножеств столбцов

Используйте аргумент i для подмножества в строки «где» должны быть сделаны изменения:

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

Как и в data.frame, мы можем подмножество, используя номера строк или логические тесты. Также возможно использовать «соединение» в i , но эта более сложная задача рассматривается в другом примере.

Редактирование атрибутов столбцов

Функции, редактирующие атрибуты, такие как levels<- или names<- , фактически заменяют объект на измененную копию. Даже если он используется только в одном столбце в таблице данных. Весь объект копируется и заменяется.

Чтобы изменить объект без копий, используйте setnames для изменения имен столбцов data.table или data.frame и setattr для изменения атрибута для любого объекта.

# 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")

Имейте в виду, что эти изменения сделаны по ссылке, поэтому они являются глобальными . Изменение их в одной среде влияет на объект во всех средах.

# 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)

Специальные символы в data.table

.sd

.SD относится к подмножеству data.table для каждой группы, за исключением всех столбцов , используемых в by .

.SD вместе с lapply может использоваться для применения любой функции к нескольким столбцам по группам в data.table

Мы продолжим использовать тот же встроенный набор данных, mtcars :

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

Среднее значение всех столбцов в наборе данных по количеству цилиндров , 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

Помимо cyl , в наборе данных есть другие категориальные столбцы, такие как vs , am , gear и carb . На самом деле нет смысла воспринимать mean этих столбцов. Поэтому давайте исключаем эти столбцы. Это где .SDcols входит в картину.

.SDcols

.SDcols указывает столбцы data.table , которые включены в .SD .

Среднее значение всех столбцов (сплошные столбцы) в наборе данных по количеству передач gear , и количество цилиндров, cyl , устроенных gear и 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

Может быть, мы не хотим вычислять mean по группам. Чтобы вычислить среднее значение для всех автомобилей в наборе данных, мы не укажем переменную by .

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

Замечания:

  • Нет необходимости заранее определять cols_chosen . .SDcols могут напрямую принимать имена столбцов
  • .SDcols также могут непосредственно брать вектор столбчатых чисел. В приведенном выше примере это будут mtcars[ , lapply(.SD, mean), .SDcols = c(1,3:7)]

.N

.N - сокращенное число строк в группе.

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

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

Написание кода, совместимого как с data.frame, так и с data.table

Различия в синтаксисе подмножества

data.table является одним из нескольких двумерных структур данных , доступных в R, помимо data.frame , matrix и (2D) array . Все эти классы используют очень похожий, но не идентичный синтаксис для подмножества, схему A[rows, cols] .

Рассмотрим следующие данные, хранящиеся в matrix : data.frame и 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!

Если вы хотите быть уверенными в том, что будет возвращено, лучше быть явным .

Чтобы получить определенные строки , просто добавьте запятую после диапазона:

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

Но, если вы хотите подмножество столбцов , некоторые случаи интерпретируются по-разному. Все три могут быть подмножеством одинаковым образом с целыми или символьными индексами, не сохраненными в переменной.

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")]  # /

Однако они отличаются для имен без кавычек

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

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

В последнем случае mycols оцениваются как имя столбца. Поскольку dt не может найти столбец с именем mycols , возникает ошибка.

Примечание: Для версии data.table пакета priorto 1.9.8, такое поведение было несколько иначе. Все, что было в индексе столбца, было бы оценено с использованием dt в качестве среды. Таким образом, оба dt[, 2:3] и dt[, mycols] вернут вектор 2:3 . mycols втором случае mycols не mycols , потому что переменная mycols существует в родительской среде.

Стратегии обеспечения совместимости с data.frame и data.table

Есть много причин писать код, который гарантированно работает с data.frame и data.table . Возможно, вы вынуждены использовать data.frame , или вам может понадобиться поделиться некоторым кодом, который вы не знаете, как будет использоваться. Итак, для удобства есть некоторые основные стратегии для достижения этого:

  1. Используйте синтаксис, который ведет себя одинаково для обоих классов.
  2. Используйте общую функцию, которая делает то же самое, что и самый короткий синтаксис.
  3. Принудите data.table вести себя как data.frame (например: вызов определенного метода print.data.frame ).
  4. Рассматривайте их как list , который они в конечном счете.
  5. Преобразуйте таблицу в data.frame прежде чем что-либо делать (плохая идея, если это огромная таблица).
  6. Преобразуйте таблицу в таблицу data.table , если зависимости не являются проблемой.

Строки подмножества. Просто, просто используйте селектор [, ] с запятой:

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

Подстрочные столбцы. Если вам нужен один столбец, используйте селектор $ или [[ ]] :

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

Если вам нужен единый способ захватить более одного столбца, необходимо немного обжаловать:

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'))

Подстрочные «индексированные» строки. Хотя data.frame имеет row.names , data.table имеет свою уникальную key функцию. Лучше всего избегать row.names и использовать существующие оптимизации в случае data.table когда это возможно.

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, ]

Получите таблицу с 1 столбцом, получите строку как вектор. Это легко понять, что мы видели до сих пор:

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

Установка ключей в data.table

Да, вам нужно SETKEY до 1.9.6

В прошлом (pre 1.9.6) ваша data.table установкой столбцов в качестве ключей к таблице, особенно для больших таблиц. [См. Интро-виньетку на стр. 5 от версии 2015 года, где скорость поиска была в 544 раза лучше.] Вы можете найти более старый код, используя эти установочные ключи с помощью «setkey» или установки столбца «key =» при настройке таблицы.

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 команды setkey . У вас может быть ключ с несколькими столбцами.

setkey(DT, y)

Проверьте ключ таблицы в таблицах ()

tables()

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

Обратите внимание, что это приведет к повторной сортировке ваших данных.

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

Теперь это не нужно

До v1.9.6 вам нужно было установить ключ для определенных операций, особенно соединяя таблицы. Разработчики data.table ускорились и внедрили функцию "on=" которая может заменить зависимость от ключей. См. « Ответ» здесь для подробного обсуждения.

В январе 2017 года разработчики написали виньетку вокруг вторичных индексов, которая объясняет синтаксис «on» и позволяет идентифицировать другие столбцы для быстрой индексации.

Создание вторичных индексов?

Аналогично ключу можно setindex(DT, key.col) или setindexv(DT, "key.col.string") , где DT - ваша таблица данных. Удалите все индексы с помощью setindex(DT, NULL) .

См. Ваши вторичные индексы с indices(DT) .

Почему вторичные индексы?

Это не сортирует таблицу (в отличие от ключа), но позволяет быстро индексировать с помощью синтаксиса «on». Обратите внимание, что может быть только один ключ, но вы можете использовать несколько вторичных индексов, что экономит необходимость повторного подключения и использования таблицы. Это ускорит подмножество при изменении столбцов, на которые вы хотите настроить.

Напомним, в примере выше y был ключом для таблицы 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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow