@你需要提高一下 R 技能了(plyr 包)

介绍

plyr 包是大神 Hadley Wickham 开发的,是这样描述的:

@你需要提高一下 R 技能了(plyr 包) - 图1

对数据进行:1.切片分割-2.应用函数-3.合并结果 ,三步操作一步搞定,极大的提升了编写代码的效率,简化代码量。对于 apply 家族函数算得上是新一代升级吧。

主要包含以下函数,都是有规律可循的,XYply格式:

  • X 代表输入数据类型,可为:a(array)、d(data frame)、l(list)等类型。
  • Y 代表输出数据类型,a(array)、d(data frame)、l(list)、(_)等类型。_ 表示什么都不输出。

具体见下:

@你需要提高一下 R 技能了(plyr 包) - 图2

使用

我们看看用 tidyverse 做个示例,按 cyl 分组计算 mpg 的均值:

  1. library(tidyverse)
  2. data("mtcars")
  3. # 按cyl分组计算mpg的均值
  4. mtcars %>% group_by(cyl) %>%
  5. summarise(mean = mean(mpg))
  6. # A tibble: 3 x 2
  7. cyl mean
  8. <dbl> <dbl>
  9. 1 4 26.7
  10. 2 6 19.7
  11. 3 8 15.1

我们可以使用 ddply ,看看用法:

  1. Usage
  2. ddply(
  3. .data, # 输入数据,数据框
  4. .variables, # 分割变量,字符串或者公式
  5. .fun = NULL, # 应用的函数
  6. ..., # 函数的其它参数
  7. .progress = "none", # 显示处理进程
  8. .inform = FALSE, # 产生过程信息
  9. .drop = TRUE,
  10. .parallel = FALSE, # 是否多线程处理
  11. .paropts = NULL
  12. )

使用,一句搞定:

  1. ddply(mtcars,.(cyl),summarise,mean = mean(mpg),sum = sum(disp))
  2. cyl mean sum
  3. 1 4 26.66364 1156.5
  4. 2 6 19.74286 1283.2
  5. 3 8 15.10000 4943.4

输出列表:

  1. # 输出列表
  2. dlply(mtcars,.(cyl),summarise,mean = mean(mpg))
  3. $`4`
  4. mean
  5. 1 26.66364
  6. $`6`
  7. mean
  8. 1 19.74286
  9. $`8`
  10. mean
  11. 1 15.1
  12. attr(,"split_type")
  13. [1] "data.frame"
  14. attr(,"split_labels")
  15. cyl
  16. 1 4
  17. 2 6
  18. 3 8

不输出:

  1. # 不输出
  2. d_ply(mtcars,.(cyl),summarise,mean = mean(mpg))
  3. # 结果啥都没有

显示进程:

  1. # 显示进程
  2. ddply(mtcars,.(cyl),summarise,mean = mean(mpg),
  3. .progress = 'text')
  4. |==================================================================| 100%
  5. cyl mean
  6. 1 4 26.66364
  7. 2 6 19.74286
  8. 3 8 15.10000

列表格式数据输入:

  1. lst <- list(a = 1:3,b = 2:4,c = 1:5)
  2. # 输出数据框
  3. ldply(lst,sum)
  4. .id V1
  5. 1 a 6
  6. 2 b 9
  7. 3 c 15
  8. # 输出列表
  9. llply(lst,sum)
  10. $a
  11. [1] 6
  12. $b
  13. [1] 9
  14. $c
  15. [1] 15

a*ply() 的特点在于含有 .margins 参数,它和 apply 很相似。对于 2 维数组, .margins 可以取 12,或者 c(1:2),对应按行切片,按列切片及每个元素进行切片,随便看一个用法:

  1. adply(
  2. .data, # 矩阵、数组、数据框
  3. .margins,
  4. .fun = NULL,
  5. ...,
  6. .expand = TRUE,
  7. .progress = "none",
  8. .inform = FALSE,
  9. .parallel = FALSE,
  10. .paropts = NULL,
  11. .id = NA
  12. )

使用示例:

  1. # 构建数组
  2. da <- array(1:10, c(4,4))
  3. da
  4. [,1] [,2] [,3] [,4]
  5. [1,] 1 5 9 3
  6. [2,] 2 6 10 4
  7. [3,] 3 7 1 5
  8. [4,] 4 8 2 6

按行求和:

  1. # 按行求和
  2. adply(da,.margins = 1,sum)
  3. X1 V1
  4. 1 1 18
  5. 2 2 22
  6. 3 3 16
  7. 4 4 20

按列求均值:

  1. # 按列求均值
  2. adply(da,.margins = 1,mean)
  3. X1 V1
  4. 1 1 4.5
  5. 2 2 5.5
  6. 3 3 4.0
  7. 4 4 5.0

操作每个元素:

  1. # 每个元素乘以10
  2. adply(da,.margins = c(1,2),.fun = function(x){x*10})
  3. X1 X2 V1
  4. 1 1 1 10
  5. 2 2 1 20
  6. 3 3 1 30
  7. 4 4 1 40
  8. 5 1 2 50
  9. 6 2 2 60
  10. 7 3 2 70
  11. 8 4 2 80
  12. 9 1 3 90
  13. 10 2 3 100
  14. 11 3 3 10
  15. 12 4 3 20
  16. 13 1 4 30
  17. 14 2 4 40
  18. 15 3 4 50
  19. 16 4 4 60

结合自定义函数应用会更加快捷方便,其它的小伙伴们自行去探索吧。