Dingrui(Frank) Zhang

R data.table的几个小技巧(一)

Frank / 2020-06-15


目前来说,在R里面manipulate data主要有两个流派,data.table 和包括 dplyrtidyr等的tidyverse

我个人来说是比较偏向于使用data.table的。其语法,性能,稳定性都优于tidyverse (一家之言见笑了)。本系列将分享一些个人的小技巧,解释不会很多,只是作为自己的一个future reference。

系列文章

R data.table的几个小技巧(一)
R data.table的几个小技巧(二)

本期内容

导入 data.table

library(data.table)

创建example data

dt <- data.table(
  Start_Date = as.Date(c(
    "2019-05-01", "2019-08-04", "2019-07-05",
    "2019-07-04", "2019-04-27", "2019-04-26",
    "2019-02-13", "2019-02-15", "2018-11-26",
    "2018-11-11"
  )),
  End_Date = as.Date(c(
    "2019-06-01", "2019-08-09", "2019-08-14",
    "2019-07-05", "2019-05-10", "2019-05-20",
    "2019-02-16", "2019-03-02", "2018-12-17",
    "2018-11-19"
  )),
  Category = c(
    "Q-Y-M-V", "E-E-E-H", "A-N-T-D",
    "J-T-B-X", "D-R-H-Z", "R-O-C-R",
    "Z-C-A-M", "O-I-J-E", "G-D-K-W", "V-Z-O-B"
  )
)
Start_Date End_Date Category
2019-05-01 2019-06-01 Q-Y-M-V
2019-08-04 2019-08-09 E-E-E-H
2019-07-05 2019-08-14 A-N-T-D
2019-07-04 2019-07-05 J-T-B-X
2019-04-27 2019-05-10 D-R-H-Z
2019-04-26 2019-05-20 R-O-C-R
2019-02-13 2019-02-16 Z-C-A-M
2019-02-15 2019-03-02 O-I-J-E
2018-11-26 2018-12-17 G-D-K-W
2018-11-11 2018-11-19 V-Z-O-B

实际操作

拆分一列到多列

dt[, paste0("Category_", 1:4) := tstrsplit(Category, split = "-")][]
##     Start_Date   End_Date Category Category_1 Category_2 Category_3 Category_4
##  1: 2019-05-01 2019-06-01  Q-Y-M-V          Q          Y          M          V
##  2: 2019-08-04 2019-08-09  E-E-E-H          E          E          E          H
##  3: 2019-07-05 2019-08-14  A-N-T-D          A          N          T          D
##  4: 2019-07-04 2019-07-05  J-T-B-X          J          T          B          X
##  5: 2019-04-27 2019-05-10  D-R-H-Z          D          R          H          Z
##  6: 2019-04-26 2019-05-20  R-O-C-R          R          O          C          R
##  7: 2019-02-13 2019-02-16  Z-C-A-M          Z          C          A          M
##  8: 2019-02-15 2019-03-02  O-I-J-E          O          I          J          E
##  9: 2018-11-26 2018-12-17  G-D-K-W          G          D          K          W
## 10: 2018-11-11 2018-11-19  V-Z-O-B          V          Z          O          B

拆分一列到多行

dt[, .(
  Start_Date = Start_Date,
  End_Date = End_Date,
  Category = unlist(strsplit(Category, split = "-"))),
  by = 1:nrow(dt)]
##     nrow Start_Date   End_Date Category
##  1:    1 2019-05-01 2019-06-01        Q
##  2:    1 2019-05-01 2019-06-01        Y
##  3:    1 2019-05-01 2019-06-01        M
##  4:    1 2019-05-01 2019-06-01        V
##  5:    2 2019-08-04 2019-08-09        E
##  6:    2 2019-08-04 2019-08-09        E
##  7:    2 2019-08-04 2019-08-09        E
##  8:    2 2019-08-04 2019-08-09        H
##  9:    3 2019-07-05 2019-08-14        A
## 10:    3 2019-07-05 2019-08-14        N
## 11:    3 2019-07-05 2019-08-14        T
## 12:    3 2019-07-05 2019-08-14        D
## 13:    4 2019-07-04 2019-07-05        J
## 14:    4 2019-07-04 2019-07-05        T
## 15:    4 2019-07-04 2019-07-05        B
## 16:    4 2019-07-04 2019-07-05        X
## 17:    5 2019-04-27 2019-05-10        D
## 18:    5 2019-04-27 2019-05-10        R
## 19:    5 2019-04-27 2019-05-10        H
## 20:    5 2019-04-27 2019-05-10        Z
## 21:    6 2019-04-26 2019-05-20        R
## 22:    6 2019-04-26 2019-05-20        O
## 23:    6 2019-04-26 2019-05-20        C
## 24:    6 2019-04-26 2019-05-20        R
## 25:    7 2019-02-13 2019-02-16        Z
## 26:    7 2019-02-13 2019-02-16        C
## 27:    7 2019-02-13 2019-02-16        A
## 28:    7 2019-02-13 2019-02-16        M
## 29:    8 2019-02-15 2019-03-02        O
## 30:    8 2019-02-15 2019-03-02        I
## 31:    8 2019-02-15 2019-03-02        J
## 32:    8 2019-02-15 2019-03-02        E
## 33:    9 2018-11-26 2018-12-17        G
## 34:    9 2018-11-26 2018-12-17        D
## 35:    9 2018-11-26 2018-12-17        K
## 36:    9 2018-11-26 2018-12-17        W
## 37:   10 2018-11-11 2018-11-19        V
## 38:   10 2018-11-11 2018-11-19        Z
## 39:   10 2018-11-11 2018-11-19        O
## 40:   10 2018-11-11 2018-11-19        B
##     nrow Start_Date   End_Date Category

根据两列生成行(多见于日期的起始)

dt[, .(
  Start_Date = Start_Date,
  End_Date = End_Date,
  Date = seq.Date(Start_Date, End_Date, by = "day"),
  Category = Category
),
by = 1:nrow(dt)
]
##      nrow Start_Date   End_Date       Date Category
##   1:    1 2019-05-01 2019-06-01 2019-05-01  Q-Y-M-V
##   2:    1 2019-05-01 2019-06-01 2019-05-02  Q-Y-M-V
##   3:    1 2019-05-01 2019-06-01 2019-05-03  Q-Y-M-V
##   4:    1 2019-05-01 2019-06-01 2019-05-04  Q-Y-M-V
##   5:    1 2019-05-01 2019-06-01 2019-05-05  Q-Y-M-V
##  ---                                               
## 167:   10 2018-11-11 2018-11-19 2018-11-15  V-Z-O-B
## 168:   10 2018-11-11 2018-11-19 2018-11-16  V-Z-O-B
## 169:   10 2018-11-11 2018-11-19 2018-11-17  V-Z-O-B
## 170:   10 2018-11-11 2018-11-19 2018-11-18  V-Z-O-B
## 171:   10 2018-11-11 2018-11-19 2018-11-19  V-Z-O-B

多列合并

dt[, .(all_category = do.call(paste, c(.SD, sep = "-"))), .SDcols = patterns("\\d$")]
##     all_category
##  1:      Q-Y-M-V
##  2:      E-E-E-H
##  3:      A-N-T-D
##  4:      J-T-B-X
##  5:      D-R-H-Z
##  6:      R-O-C-R
##  7:      Z-C-A-M
##  8:      O-I-J-E
##  9:      G-D-K-W
## 10:      V-Z-O-B

还可以用于多列相加,相乘等。