美文网首页
R语言编程-Tidyverse 书籍 - data.table

R语言编程-Tidyverse 书籍 - data.table

作者: Hello育种 | 来源:发表于2022-10-07 01:30 被阅读0次

data.table 包能胜任各种数据操作,速度查快。其语法高度抽象、简洁、一致。

image.png

用i 选择行,用j 操作列,根据by 分组. 其中j表达式非常强大和灵活,可以选择,修改,汇总和计算新列。

引用语法“ := ”

data.table

设置键和引索,使得选择行、做数据连接更加方便快速(快170 倍)。

  • 键:一级有序索引(在内存中做物理重排序)
  • 索引:自动二级索引数学只保存为属性, ==, %in%()


    image.png

特殊符号

image.png

管道操作

da[...][...][...]

批量读入

c("DT.csv", "DT.csv") %>%
    lapply(fread) %>%
    rbindlist() # 多个数据框/列表按行合并

vroom包提供了速度更快的文件读写函数:vroom, vroom_write()

非等连接(筛选范围值)

一般的连接是等值连接,即匹配列的值相等,才认为匹配成功。

很多时候需要非等连接,相当于是按条件连接,即匹配列的值不要求必须相等,只要满足一定条
件就认为是匹配成功,再将匹配成功的其他列连接进来。

滚动连接

滚动连接也是很有用的一种数据连接,往往涉及日期时间,特别是处理在时间上有先后关联的两
个事。

x[y, on = .(id = id, date = date), roll = TRUE] # 同roll = inf

根据id 等值匹配行,date 是滚动匹配,匹配与左表y 日期最接近的前一个日期,匹配成功的列
合并进来;roll = -inf 则匹配最接近的后一个日期

使用

首先创建用于连接的单独时间列
再设置key##这样就可以省略on语句


image.png

需要确定哪一个数据作为左表(连接起始)

image.png

可以做窗口连接, 并且可以做滚动窗口连接

数据重塑

宽变长

使用的语句:
每行只有一个观察值的情况:
data %>% melt(measure = , variable = " ", value = " " )## measure后面是整数向量指定要变形的列, variable增加新的列名字,value,值的去向设定,如果要忽略缺失值,设置: na.rm = T
tidyr::pivot_longer()也可以实现
每行只有多个个观察值的情况:
data %>% melt(measure = patterns(列明) , value = " ", na.rm=T )#

长变宽

只有1 个列名列和1 个值列的情形
data %>% dcast (year ~ Type, value = "Heads", fill = 0)##第一个参数是公式形式, ~左边是不变的列,右边是“变量名”来源,参数value指定“值”的来源

pivot_wider()
data %>% pivot_wider(names_from = Type, values_from_Heads, values_fill = 0)

有多个列名列和多个值列的情形

image.png

数据分割与合并

函数split(DT, by) 可将data.table 分割为list, 然后就可以接map_*() 函数逐分组迭代。

将rate列拆为两列,并且删除原列

data[, c("cases", "population") := tstrsplit(data$rate, split = "/")] [, rate := NULL]

合并列

data[, new := past0(century, year)] [, c("century", "year") := NULL]

数据操作

对行操作,使用data[i, j, by]中的i

选择行: dt[V4 %chin% c("A", "B")] ##比 %in%更快

unique()删除重复行
na.omit(data, cols = 1:4)## 删除1到4列,包含NA的行

行切片

data[sample(.N, 3)]## 随机抽取3行
data[sample(.N, .N* 0.5)] ## 随机抽取50% 的行

data[v4 %like% "^B"] ##V4列以B开头
data[v2 %between% c(3,6)] ###选择v2列中3到6的行,包含3与6
data[between (v2, 3, 5, incbounds = F)] ## 开区间
data [v2 %inrange% list (-1:1, 1:3)] ## v2列中多个区间值的选择
data[inrange(v2, -1:1. 1:3, incbounds = T)]## v2列中多个区间值的选择

排序order

data[order(v1)]

对行操作,使用data[i, j, by]中的j

根据引索

data[[3]]或者data[,3]

根据列名

data[, .(V3)]或者data[, .(v2, v3, v4)]

反引用列名

data.table 需要字符串函数、正则表达式构造出列名向量,再通过反引用选择相应的列。
首先确定需要选择的列名:

image.png image.png

选取列:
data[, ..cols]

调整序列

cols = rev(names(DT)) ### 自己可以排序
setcolorder(DT, cols) ## 设定

修改列名

setnames(data, old, new)

修改因子水平

data[, setattr(sex, "levels", c("M", ""F))]

注意: data.table 是使用** := **直接对原数据框修改

修改或增加一列
data[, v1 := v1^2] ##只修改列
data[, v2 := v1^2 ## 增加v2列
data[, .(v2 = log(v1), v3 = v2 + 1) # 只保留新列,但是注意第二个v2使用的是原始v2
data[, c("v2","v3") := .(temp <- log(v1), v3 = temp +1)] ## 这里第二个v2使用的是新计算的列

同时增加多列

data[, ':=' (v6 = sqrt(v1),
v7 = "x")] ## v7列的值全为x

同时修改多列

需要借助lapply()和特殊符号:
.SD: 每个分组的数据子集, 除了by或者keyby的列
.SDcols: 与.SD 连用,用来选择包含在.SD 中的列,支持索引、列名、连选、反选、正则表达式、条件判断函数

应用函数到所有的列

data[, lapply(.SD, as.character)]

注意,上述同时修改多列的代码,都是只保留新列,若要保留所有列,需要准备新列名cols, 再在j 表达式中使用(cols) := ...

删除列

data [, c("v1", "v3") := NULL]

从新编码

data[v1 < 0, v1 := 0]  ## 单个编码
data[, v1 := fifelse(v1 < 0, -v1, v1)]## 二分支
data[, v2 := fcase(v2 < 0, "low",
                             v2 < 4, "middle",
                            default = "high")]

前移/后移运算

shift(x, n= 1, fill = NA, type = "lag") ## 1, 2, 3 变为 NA, 1, 2
shift(x, n = 1, fill = NA, type = "lead") ## 1, 2, 3 变为 2, 3, NA

分组汇总

data.table 是根据bykeyby分组,
区别是,keyby 会排序结果并创建键,使得更快地访问子集。
分组数据框,相当于整个数据框分成了m 个数据框,数据操作是分别在每个数据框上进行,若汇总则得到的是m 个结果。

简单的分组汇总

按性别分组计算

data[,    .(n = .N, 
             math_avg = mean(math, na.rm = T),
             math_med = median(math)),
             by = sex]

对时间的处理IDataTime

image.png

对某些列做汇总

data[, lapply(.SD, mean), .SDcols = patterns("h"), 
          by = .(class, sex)]  

对所有的列做汇总

data[, name := NULL][, lapply(.SD, mean, na.rm = T), by = .(class, sex)]

对满足条件的列做汇总

data[, lapply(.SD, mean, na.rm = T), by = class,
.SDcols = is.numeric]

分组计数

data[, Bin := cut(math, c(0, 60, 100))]
data[CJ(class = class, Bin = Bin, unique = TRUE),
     on = c("class","Bin"), .N, by = .EACHI]

其中CJ() 相当于expand_grid(0, 生成所有两两组合

分组选择行

first(), last(), uniqueN(). 比如提取每组的first/nth 观测:


image.png

重点: 在使用中对于data[i, j, by], 同时对i 选择的行,根据by 分组,做j 操作

data.table 中习惯用lapply(), 换成map() 也是一样的,好处是支持函数的purrr-风格公式写法。

相关文章

网友评论

      本文标题:R语言编程-Tidyverse 书籍 - data.table

      本文链接:https://www.haomeiwen.com/subject/hgveprtx.html