R 语言中的 data.table
包可以理解为 data.frame
的高级版本,它比较适合适合用来处理大型数据集。
载入包并且读取一些数据,当然也可以使用 nrow
参数来决定读取多少行:
library(data.table)
mydata <- fread("some_kind_of_data.csv")
mydata <- fread("some_kind_of_data.csv", nrows = 10)
data.table
包提供了一个非常简洁的通用格式:mydata[i, j, by]
,可以理解为:对于数据集mydata
,选取子集行i
,通过by
分组计算j
。只需要记住,i
是用来在行上进行操作的(比如筛选行),j
是用来在列上进行操作的(比如选择列或者根据计算创建新列)。对比dplyr
等包来说,data.table
的运行速度更快。
选择列
如果只需要选择列的话,可以只代入 j
,但需要记住给 i
留出位置:
mydata[, j]
首先,通过列名选择列是,是否需要打双引号是一个值得考虑的问题,因为两者各有优劣。
data.table
支持打双引号的原生 R
的做法:
data1 <- mydata[, c("columnA", "columnB", "columnC", "columnD")]
但也可以使用不打双引号,这样会更方便(就好像 tidyverse 里面的 select
),只不过需要用到 list
:
data1 <- mydata[, list(columnA, columnB, columnC, columnD)]
这里,第一个小技巧就来了,我们可以使用一个点代替 list
:
data1 <- mydata[, .(columnA, columnB, columnC, column)]
在 data.table
的中括号里,.()
就是 list()
的简写形式。
如果你想使用一个已经存在的列名向量,比如:
mycols <- c("columnA", "columnB", "columnC", "columnD")
直接套用是行不通的:mydata[, mycols]
,而是需要在这个列名向量前面加两个点:
data1 <- mydata[, ..mycols]
当然,你可以借用命令行里面 ..
的含义去理解,可以认为是从括号里面的命名空间上升到全局变量了。
计算 data.table 行数
下一个标记是 .N
,代表行数。可以用这个标记来得到数据集的总行数和使用 by
分组后的各亚组行数。
比如我们返回 iris
数据集的总行数和按照 Species
分组的行数:
diris <- as.data.table(iris)
diris[, .N]
# 150
diris[, .N, Species]
# Species N
# 1: setosa 50
# 2: versicolor 50
# 3: virginica 50
当然,使用多个变量进行分组也是可以的,同样用到 .
:
mydata[, .N, .(columnA, columnB)]
并且你还可以在后面使用 order
,让行数结果从高到低排列:
mydata[, .N, .(columnA, columnB)][order(columnA, -N)]
这样的语句顺序也非常符合数据处理的逻辑。
当然,如果你使用习惯了 dplyr
,你喜欢的写法 data.table
也可以模仿:
mydata %>%
count(columnA, columnB) %>%
order(columnA, -n)
mydata[, .N,
.(columnA, columnB)][
order(columnA, -n)
]
向 data.table 增加列
比如我们想要在 iris
数据集增加一列,看品种是否是 Virginica
,如果是则为 TRUE
,否则为 FALSE
,
那么可以这样写:
diris[, IfVirginica := ifelse(Species %like% "virgin", TRUE, FALSE)]
这个 %like%
的用法有点类似于 SQL 里面的 LIKE
。
而 :=
的用法可能在其他编程语言中比较常见,这里代表通过增加新列改变了目前的数据集 diris
,
而并非存入另外的新数据集。
当然也可以同时增加两列:
diris[, `:=`(
IfVirginica := ifelse(Species %like% "virgin", TRUE, FALSE),
IfVensicolor := ifelse(Species %like% "vensi", TRUE, FALSE)
)]
更多的操作符
%between%
:找到目标的取值区间进行筛选
mydata <- diris[Species == "virginica" & Sepal.Length %between% c(4, 6)]
%chin%
:类似原生 R 的 %in%
,但只面向字符变量且速度更快
mydata <- diris[Species %chin% c("virginica", "vensicolor")]
fcase() 函数
最后要介绍的 fcase()
函数和 SQL 里面的 CASE WHEN
语句和 dplyr
里面的 case_when()
语句
类似,基本语法是 fcase(condition1, "value1", condition2, "value2")
,比如下面的例子:
diris[, newSpeices := fcase(
IfVirginic & !IfVensicolor, "Species1",
!IfVirginic & IfVensicolor, "Species2",
IfVirginic & IfVensicolor, "Both",
!IfVirginic & !IfVensicolor, "Neither")]
最后,更多特殊符号的用法可以参考 help("special-symbols")
,虽然文档可能讲得不是很清楚,但依然全面。