利用 data.table 包变形数据
一. 基础概念
data.table 这种数据结构相较于 R 中本源的 data.frame 在数据处理上有运算速度更快, 内存运用更高效, 可认为它是 data.frame 的升级版. 同时, data.table 包具备更多更强的功能, 它基本工作形式是,
dt [i, j, by]
dt 为 data.table 结构
i 为行, j 为列, by 为分组
二. 创建 data.table
和 data.frame 一样, 如下:
- data.table(a=c(1, 2), b=c("a", "b"))
- a b
- 1: 1 a
- 2: 2 b
转化 data frame 或 list 为 data.table, 使用 setDT(df) (仅限于 data.frame 和 list),as.data.table(df)(使用范围更广)
三. 取子集
3.1 行向 (rows):
3.1.1. 以 row numbers,dt [1:2, ]
3.1.2. 以条件 (本质上是逻辑值 TRUE OR FALSE), dt [a>5, ]
有如下逻辑操作符:
- <<= is.na() %in% | %like%
- >>= !is.na() ! & %between%
3.2 列向 (columns):
3.2.1. 抽提 (同行, 与 data.frame 一致)
- dt [, c(2)]
- dt [, .(b, c)]
3.2.2. 归纳
dt [, .(x=sum(a))] -- 创建一个新 data.table 用 a 列的和
其他函数如: mean,median, min, max 等等
3.2.3. 计算列 (在:= 接上计算表达式)
- dt [, c:=1+2]
- dt[a == 1, c := 1 + 2]
dt[,`:=`(c = 1 , d = 2)] -- 计算分开计算多列
- a b c d
- 1: 1 a 1 2
- 2: 2 b 1 2
3.2.4. 删除某列
dt[,c := NULL]
3.2.5. 转换某列
dt[,b := as.integer(b)] - 如 as.integer(), as.numeric(),as.character(), as.Date() 等函数
四. 分组 (by)
dt[, j, by = .(a)] -- 由 a 列内容进行分组
dt[, j, keyby= .(a)] -- 由 a 列内容进行分组, 同时分类排序
常规分组操作:
dt[, .(c = sum(b)), by = a] - 以 a 列分组来计算 b 列和
dt[,c := sum(b), by = a] - 创建新列 c 来储存按 a 列分组来计算 b 列和的结果
dt[, .SD[1], by = a] - 抽提 a 列分组的第一行
dt[, .SD[.N], by = a] - 抽提 a 列分组的最后一行
五. 链式操作
dt[...][...]
六. data.table 的功能函数 (重点)
6.1 重排
setorder(dt, a, -b) -- a 列升序, b 列降序 (-)
注意: data.table 中以 "set" 为前缀的功能函数以及操作符 ":=" 行使功能时, 在内存中不创建副本, 因此 setDT(df) 比 df <- as.data.table(df) 更高效.
6.2 去重
unique(dt, by = c("a", "b")) -- 依次去重 a, b 列
uniqueN(dt, by = c("a", "b")) -- 计数去重后的行数
6.3 修改列名
setnames(dt, c("a","b"), c("x", "y"))
6.4 设置键 (SET KEYS)
setkey(dt, a, b) -- 设置键是为快速重复查找特殊列用 dt[.(value), ], 或者是为了合并列用 dt_a[dt_b]
七. 合并 data.tables
7.1 按列合并
dt_a[dt_b,on = .(b = y)] -- 用于两个 data.table 有相同列的合并, 如 dt_a 的 b 列与 dt_b 的 y 列相同
dt_a[dt_b,on = .(b = y, c> z)] -- 上式的扩展, 不仅用于相同列, 更用于带有条件的合并, 如不仅满足 dt_a 的 b 列与 dt_b 的 y 列相同, 而且要满足 dt_a 的 c 列大于 dt_b 的 z 列
7.2 滚动合并
dt_a[dt_b, on = .(id = id, date = date), roll = TRUE] -- 不仅按 id,data 进行匹配, 同时保持向最近一行进行匹配
7.3 全合并
rbind(dt_a, dt_b) -- 行合并
cbind(dt_a, dt_b) -- 列合并
八. 重构 data.table(与 reshape2 包相似)
长数据 变 宽数据
dcast(dt, id ~ y, value.var= c("a", "b"))
宽数据 变 长数据
- melt(dt,
- id.vars= c("id"),
- measure.vars= patterns("^a", "^b"),
- variable.name = "y",
- value.name = c("a", "b"))
九. 应用 Apply 函数
- dt[, lapply(.SD, mean), .SDcols = c("a", "b")] ---
- e.g. mean(), as.character(),
- which.max().
- cols <-c("a")
- dt[, paste0(cols, "_m") := lapply(.SD, mean),
.SDcols = cols] --- 重命名运算后的列
十. 对连续行计数
dt[, c := 1:.N, by = b] -- 分组后, 计数行数, 即计算每组有多少行
dt[, c := shift(a, 1), by = b]
十一. 读取和写入文件
fread("file.csv")
fread("file.csv", select = c("a", "b")) 这个函数很强大, 除了读文件以外, 可以直接读网址
fwrite(dt, "file.csv") 写入文件
来源: https://www.cnblogs.com/duanxiaoqian/p/datatable_package_tricks.html