【发布时间】:2017-01-21 15:54:25
【问题描述】:
我正在尝试清理数据框,并且我想将一列中的 NA 替换为另一列中的相应值。我也想一次为多个列执行此操作。
示例数据框。
set.seed(123)
dates <- seq(as.Date("2016-01-01"), by = "day", length = 10)
names <- rep(c("John Doe", "Jane Smith"), each = 5)
var1_group <- runif(10)
var2_group <- runif(10)
var1_person <- runif(10)
var2_person <- runif(10)
myDF <- data.frame(names, var1_group, var2_group, var1_person, var2_person)
myDF <- cbind(dates, myDF)
使用 dplyr 进行一些操作后...
myDF <- myDF %>% mutate_each(funs(lag), contains("group"))
myDF <- myDF %>% group_by(names) %>% mutate_each(funs(lag), contains("person"))
我得到了一堆 NA...
dates names var1_group var2_group var1_person var2_person
1 2016-01-01 John Doe NA NA NA NA
2 2016-01-02 John Doe 0.2875775 0.95683335 0.8895393 0.9630242
3 2016-01-03 John Doe 0.7883051 0.45333416 0.6928034 0.9022990
4 2016-01-04 John Doe 0.4089769 0.67757064 0.6405068 0.6907053
5 2016-01-05 John Doe 0.8830174 0.57263340 0.9942698 0.7954674
6 2016-01-06 Jane Smith 0.9404673 0.10292468 NA NA
7 2016-01-07 Jane Smith 0.0455565 0.89982497 0.7085305 0.4777960
8 2016-01-08 Jane Smith 0.5281055 0.24608773 0.5440660 0.7584595
9 2016-01-09 Jane Smith 0.8924190 0.04205953 0.5941420 0.2164079
10 2016-01-10 Jane Smith 0.5514350 0.32792072 0.2891597 0.3181810
我现在想做的是将 *_person 列中的 NA 替换为 *_group 列中的相应值。 (见第 6 行)
dates names var1_group var2_group var1_person var2_person
1 2016-01-01 John Doe NA NA NA NA
2 2016-01-02 John Doe 0.2875775 0.95683335 0.8895393 0.9630242
3 2016-01-03 John Doe 0.7883051 0.45333416 0.6928034 0.9022990
4 2016-01-04 John Doe 0.4089769 0.67757064 0.6405068 0.6907053
5 2016-01-05 John Doe 0.8830174 0.57263340 0.9942698 0.7954674
6 2016-01-06 Jane Smith 0.9404673 0.10292468 0.9404673 0.1029246
7 2016-01-07 Jane Smith 0.0455565 0.89982497 0.7085305 0.4777960
8 2016-01-08 Jane Smith 0.5281055 0.24608773 0.5440660 0.7584595
9 2016-01-09 Jane Smith 0.8924190 0.04205953 0.5941420 0.2164079
10 2016-01-10 Jane Smith 0.5514350 0.32792072 0.2891597 0.3181810
这适用于一列...
myDF$var1_person <- ifelse(is.na(myDF$var1_person), myDF$var1_group, myDF$var1_person)
但我想同时为所有列执行此操作。在我的实际数据框中,每组大约有 20 列。我已经尝试了很多其他的东西,但我不想用我的废话来混淆这篇文章。
*如果您可以根据列前缀获得匹配 n 个变量的代码,则可获得奖励积分。
var1_group > var1_person
var2_group > var2_person
...
varn_group > varn_person
【问题讨论】:
-
您的问题出现是因为您的数据不整洁 - 您在列名中编码了一些索引值。将您的数据融合为长格式(1 个人员列、1 个组列、1 个索引列),然后进行替换,返回宽格式。请参阅
reshape2或tidyr了解长格式和宽格式之间的转换。 -
另外,由于您已经在使用
dplyr,coalesce(var1_person, var1_group)等同于您的ifelse()语句。 -
这种方法的效率如何?对于一个非常大的数据框,比如 1 百万行和 100 列,这仍然可行吗?我在想我也可以尝试
apply类似coalesce(col_list_person, col_list_group) -
估计并不难:1MM 行和 100 列表明每个索引大约有 50 列,因此长格式大约有 50MM 行(只有约 3 列,加上任何日期/名称您拥有的 ID 列)。取决于你的机器。我会这样做,因为我可能永远不会回到宽格式 - 长格式往往更通用。如果这是您想要对每个列对进行的唯一操作,则可能不值得。但是,如果您想对每一列对做很多事情,那么使用
data.table或dplyr的长格式非常容易。