引言:几个月前用过 tidyr 包,这回再去用,发现把一些参数忘得一干二净,无法接受自己的忘性。故整理出来,加深理解。

宽转长 Wide2Long

tidyr::gather(data, key, value, ..., na.rm = FALSE, convert = FALSE, factor_key = FALSE)

参数:

  • data 数据框
  • key 键,新生成的因子列名(不需要加引号)
  • value 值,新生成的数值列名(不需要加引号)
  • ... 所指定的需要转换的列,使用变量名,即原来数据框的列名。变量名将构成合并的键的因子。有以下几种表示方式:
    • x:z 选择所有的 x 与 z 之间的变量(包括 x 和 z)
    • -z 排除 z 变量
    • x,y,z 选择 x y z 三个变量
    • 2:4 选择第2到4列
  • na.rm 是否去除缺失值
  • convert 自动转换键列的值的数据类型,当需合并的列名为数值,整数,或逻辑值时非常有用
  • factor_key 是否将键的内容转换为因子,默认为 FALSE 即存储为字符向量

长转宽 Long2Wide

tidyr::spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE, sep = NULL)

参数:

  • key 该列的因子转换为多个列的列名
  • value 该列的内容将分配到多个列中
  • fill 指定填充缺失值的值
  • convert 数据类型转换
  • drop 是否丢弃数据中不存在的因子水平,如果为 FALSE,那么将把没有数据的因子的值使用 fill 的参数值填充。
  • sep 如果为 NULL,新列名为键所在的列的值;如果不为 NULL,列名将为 <key_name><sep><key_value>,即键所在的列名加上分隔字符加键所在的列的值。例如:如果 keyA,A 有两个因子水平,A1,A2sep="-",那么列名将为 A-A1,A-A2

分割单列为多列

tidyr::separate(data, col, into, sep = "[^[:alnum:]]+", remove = TRUE, convert = FALSE, extra = "warn", fill = "warn", ...)

参数:

  • col 列名(不需要引号)
  • into 字符串向量,例如 c("x", "y"),分隔的列的列名就是 x 和 y。
  • sep 分隔符,取值可以为正则表达式,也可以为数值。分隔符的长度必须比 into 少1。
    • 如果为字符串,那么被当作正则表达式处理。默认值为匹配任意非字母和数字的符号。
    • 如果为数值,被当作分隔的位置。正数表示从第1个字符开始数,负数表示从右边第1个字符开始数。
  • remove 是否剔除输入列,默认为 TRUE,表示将 colinto 剔除。
  • convert 数据类型转换。
  • extra 如果 sep 为字符向量,且值太多,使用该参数控制结果
    • "warn" 默认值,发出警告,并丢弃多余的值
    • "drop" 丢弃多余的值,不发出警告
    • "merge" 分割的次数为 into 长度数目
  • fill 如果 sep 为字符向量,且值不足,使用该参数控制结果
    • "warn" 默认值,发出警告,从右往左填充
    • "right" 在右侧填充
    • "left" 在左侧填充

对于 extrafill 参数不熟悉。

合并多列为单列

tidyr::unite(data, col, ..., sep = "_", remove = TRUE)

参数:

  • col 将要合并得到的列名
  • ... 指定要被合并的列名,表示方式和 tidyr::gather 一样
  • sep 分隔符
  • remove 默认为 TRUE,删除输入列,即 ... 中的列

实例

library(tidyr)
data.long <- data.frame(
  id = rep.int(c(1,2,3), 2),
  key = rep(c("f1","f2"), each = 3),
  value = sample(6, 6, replace = TRUE)
)
>>> data.long
id key value
1  1  f1     4
2  2  f1     6
3  3  f1     5
4  1  f2     3
5  2  f2     6
6  3  f2     5

长转宽

data.wide <- spread(data.long, key = key, value = value)
>>> data.wide
id f1 f2
1  1  4  3
2  2  6  6
3  3  5  5

宽转长

data.long <- gather(data.wide, key = key, value = value, f1, f2)
## data.long <- gather(data.wide, key = key, value = value, f1:f2)
## data.long <- gather(data.wide, key = key, value = value, 2:3)

合并列与分割列

#### 新加一列
data.long$g <- rep(c("g1","g2"), each = 3)
>>> data.long
id key value  g
1  1  f1     4 g1
2  2  f1     6 g1
3  3  f1     5 g1
4  1  f2     3 g2
5  2  f2     6 g2
6  3  f2     5 g2

#### 合并 key 和 g
data.long.unite <- unite(data.long, col = grp_key, key, g, sep = "-")
>>> data.long.unite
id grp_key value
1  1   f1-g1     4
2  2   f1-g1     6
3  3   f1-g1     5
4  1   f2-g2     3
5  2   f2-g2     6
6  3   f2-g2     5

#### 分割列为多列
data.long.sep <- separate(data.long.unite, col = grp_key, into = c("key", "grp"), sep = "-")
>>> data.long.sep
id key grp value
1  1  f1  g1     4
2  2  f1  g1     6
3  3  f1  g1     5
4  1  f2  g2     3
5  2  f2  g2     6
6  3  f2  g2     5

该文章同时在作者个人博客发布。

拓展阅读: