13.3 操作数据框

许多数据清理的任务涉及数据框的操作,要把它们转换成相应所需的形式。我们已知可用索引和subset函数来选择数据框的子集。其他常见任务,包括通过添加其他列(或替换现有列)来扩充数据框、处理缺失值,以及在数据框的宽和长格式之间的转换。以下有几个函数可用于在数据框中添加或替换列。

13.3.1 添加和替换列

假设要为english_monarchs数据框添加一列来表示统治者执政了多少年,我们可以使用标准的赋值操作符来完成:

  1. english_monarchs$length.of.reign.years <-
  2. english_monarchs$end.of.reign - english_monarchs$start.of.reign

这是可行的,但要反复输入数据框变量名无论是对于输入或阅读来说都太麻烦。with函数可以通过直接调用变量使之简化。它接受一个数据框2和要计算的表达式作为输入参数:

2或环境。

  1. english_monarchs$length.of.reign.years <- with(
  2. english_monarchs,
  3. end.of.reign - start.of.reign
  4. )

within函数的工作方式类似,但它会返回整个数据框:

  1. english_monarchs <- within(
  2. english_monarchs,
  3. {
  4. length.of.reign.years <- end.of.reign - start.of.reign
  5. }
  6. )

在此例中within还需输入更多。当要更改多个列时,它更有用:

  1. english_monarchs <- within(
  2. english_monarchs,
  3. {
  4. length.of.reign.years <- end.of.reign - start.of.reign
  5. reign.was.more.than.30.years <- length.of.reign.years > 30
  6. }
  7. )

也就是说,如果你正在创建或改变某一列,就使用with;如果你想一次操作多个列,则用within

plyr包中的mutate函数采取了另一种方法,它接受新的和更改的列,并把它们当成“名称-值”对 3:

3R基本包中的transform函数是mutate函数的早期实现,现已过时。

  1. english_monarchs <- mutate(
  2. english_monarchs,
  3. length.of.reign.years = end.of.reign - start.of.reign,
  4. reign.was.more.than.30.years = length.of.reign.years > 30
  5. )

13.3.2 处理缺失值

在第12章,马鹿数据集显示了用四种不同方式测量得出每头鹿的颅容量。对其中某些而非所有的鹿,会进行第二次测量以测试该技术的可重复性。这意味着某些行会有缺失值。complete.cases函数告诉我们哪些行没有缺失值:

  1. data("deer_endocranial_volume", package = "learningr")
  2. has_all_measurements <- complete.cases(deer_endocranial_volume)
  3. deer_endocranial_volume[has_all_measurements, ]
  4. ## SkullID VolCT VolBead VolLWH VolFinarelli VolCT2 VolBead2 VolLWH2
  5. ## 7 C120 346 335 1250 289 346 330 1264
  6. ## 8 C25 302 295 1011 250 303 295 1009
  7. ## 9 F7 379 360 1621 347 375 365 1647
  8. ## 10 B12 410 400 1740 387 413 395 1728
  9. ## 11 B17 405 395 1652 356 408 395 1639
  10. ## 12 B18 391 370 1835 419 394 375 1825
  11. ## 13 J7 416 405 1834 408 417 405 1876
  12. ## 15 A4 336 330 1224 283 345 330 1192
  13. ## 20 K2 349 355 1239 286 354 365 1243

捷径为na.omit函数,它能删除数据框中所有带有缺失值的行4:

4na.excludena.omit的行为一样,两者同存为惯例。

  1. na.omit(deer_endocranial_volume)
  2. ## SkullID VolCT VolBead VolLWH VolFinarelli VolCT2 VolBead2 VolLWH2
  3. ## 7 C120 346 335 1250 289 346 330 1264
  4. ## 8 C25 302 295 1011 250 303 295 1009
  5. ## 9 F7 379 360 1621 347 375 365 1647
  6. ## 10 B12 410 400 1740 387 413 395 1728
  7. ## 11 B17 405 395 1652 356 408 395 1639
  8. ## 12 B18 391 370 1835 419 394 375 1825
  9. ## 13 J7 416 405 1834 408 417 405 1876
  10. ## 15 A4 336 330 1224 283 345 330 1192
  11. ## 20 K2 349 355 1239 286 354 365 1243

相反地,如果你的数据框中包含任何缺失值,na.fail将抛出一个错误:

  1. na.fail(deer_endocranial_volume)

这两个函数也可以对向量进行缺失值删除或者抛出错误,就像在数据框中一样。

可以采取统计上可行的多次插补来填补缺失值。这已超出本书的范围,不过我们建议你从micemix包开始研究。

13.3.3 在宽和长表格之间进行转换

马鹿数据集包含了以四种不同方式获得的鹿头骨颅容量数据。它的每一列包含了对某种类型的鹿的测量结果。(为简单起见,我们忽略了重复测量的列。)这就是数据框的形式:

  1. deer_wide <- deer_endocranial_volume[, 1:5]

从另一个角度看,每一列中的头骨测量数据都是同一类型的东西(即测量值),只是测量的方式不同。因此,另一种表示该数据的方式是:每个鹿都有4行数据,每行有以下几列:一列是和之前一样颅骨的ID(所以每个值将被重复四次),一列为测量值,还有一列用于解释本行所在的测量类型的因子。这就是所谓的数据框的格式。

R的基础包中reshape的函数能用于宽和长形式之间的转换。它的功能非常强大,但并不太直观。更好的选择是使用reshape2包中的功能。

在这个包中可用melt函数将宽形式转换成长形式5。我们选择SkullID作为ID列(与其他所有都被归为一次测量):

5术语“melting”及其反义词“casting”均参考自钢铁行业。

  1. library(reshape2)
  2. deer_long <- melt(deer_wide, id.vars = "SkullID")
  3. head(deer_long)
  4. ## SkullID variable value
  5. ## 1 DIC44 VolCT 389
  6. ## 2 B11 VolCT 389
  7. ## 3 DIC90 VolCT 352
  8. ## 4 DIC83 VolCT 388
  9. ## 5 DIC787 VolCT 375
  10. ## 6 DIC1573 VolCT 325

或者,使用measure.vars参数,它显示除了id.vars列之外的其他所有列。在这种情况下,工作量会变大,但当有很多的ID变量和极少测量变量时,它很有用:

  1. melt(deer_wide, measure.vars = c("VolCT", "VolBead", "VolLWH", "VolFinarelli"))

dcast函数能把长转换回宽形式,并将结果返回为一个数据框(相关函数acast返回一个向量、矩阵或数组):

  1. deer_wide_again <- dcast(deer_long, SkullID ~ variable)

我们重构的数据集deer_wide_again与原来的deer_wide基本一样,除了它按SkullID中的字母顺序排序。

注意

电子表格的爱好者可能会注意到,acastdcast能有效地创建数据透视表。

13.3.4 使用SQL

sqldf包提供了使用SQL操作数据框的方式。一般情况下,标准R里面的函数都比SQL代码要更简洁、可读性也更好。不过,当你原来的工作背景是数据库,这个包能帮你平滑过渡到R:

  1. install.packages("sqldf")

下例将比较标准R和sqldf版本的子集查询语句:

  1. library(sqldf)
  2. ## Loading required package: DBI
  3. ## Loading required package: gsubfn
  4. ## Loading required package: proto
  5. ## Loading required namespace: tcltk
  6. ## Loading required package: chron
  7. ## Loading required package: RSQLite
  8. ## Loading required package: RSQLite.extfuns
  9. subset(
  10. deer_endocranial_volume,
  11. VolCT > 400 | VolCT2 > 400,
  12. c(VolCT, VolCT2)
  13. )
  14. ## VolCT VolCT2
  15. ## 10 410 413
  16. ## 11 405 408
  17. ## 13 416 417
  18. ## 16 418 NA
  19. query <-
  20. "SELECT
  21. VolCT,
  22. VolCT2
  23. FROM
  24. deer_endocranial_volume
  25. WHERE
  26. VolCT > 400 OR
  27. VolCT2 > 400"
  28. sqldf(query)
  29. ## Loading required package: tcltk
  30. ## VolCT VolCT2
  31. ## 1 410 413
  32. ## 2 405 408
  33. ## 3 416 417
  34. ## 4 418 NA