2017-10-16 80 views
1

我有一个相当大的数据框(70k×900),其中包含ID,日期和~900个代码列。代码缺失的地方,我想填补这些缺失的值。通过分组ID和日期有效地填充缺失值

规则是,对于每个包含未在以后的日期记录的代码的ID,它应该结转。

我已经将我的数据框转换为宽格式(假设这是最简单的方法来减少值)。

见例如DF:

df <- as.data.frame(list(
id = c('p1', 'p1', 'p1', 'p2', 'p2', 'p2'), 
date = as.Date(1:6, origin=Sys.Date()), 
code_1 = c('c_1', NA, NA, 'c_1', NA, NA), 
code_2 = c(NA, 'c_2', NA, NA, NA, NA), 
code_3 = c(NA, NA, 'c_3', NA, NA, NA))) 

我想返回类似以下,其中代码依次填写:

df2 <- as.data.frame(list(
id = c('p1', 'p1', 'p1', 'p2', 'p2', 'p2'), 
date = as.Date(1:6, origin=Sys.Date()), 
code_1 = c('c_1', 'c_1', 'c_1', 'c_1', 'c_1', 'c_1'), 
code_2 = c(NA, 'c_2', 'c_2', NA, NA, NA), 
code_3 = c(NA, NA, 'c_3', NA, NA, NA))) 

我曾尝试以下:

df[, lapply(FUN = na.locf, na.rm = FALSE), by = .(id)] 

但是由于尺寸的原因,我的电脑无法处理,因此解决方案必须高效。

真的很感谢任何帮助。

+0

是唯一的每个ID代码,即一旦P1在code_1已C_1可以将其在不同的代码code_1以后? – kath

+1

您正试图在dataframe上使用'data.table'语法,这是行不通的。使用'library(data.table); setDT(df)[,3:5:= lapply(.SD,na.locf,na.rm = FALSE),by = id,.SDcols = 3:5] []'应该完成这项工作。 – Jaap

+0

@kath感谢您的评论。这些代码对于每个ID都不是唯一的,但是考虑到数据帧的构造,只有code_1会出现在code_1列中。我希望这是有道理的? – avocet

回答

0

您可以使用filltidyr

library(dplyr) 
library(tidyr) 
df %>% 
    group_by(id) %>% 
    fill(code_1:code_3) 

结果:

# A tibble: 6 x 5 
# Groups: id [2] 
     id  date code_1 code_2 code_3 
    <fctr>  <date> <fctr> <fctr> <fctr> 
1  p1 2017-10-17 c_1  NA  NA 
2  p1 2017-10-18 c_1 c_2  NA 
3  p1 2017-10-19 c_1 c_2 c_3 
4  p2 2017-10-20 c_1  NA  NA 
5  p2 2017-10-21 c_1  NA  NA 
6  p2 2017-10-22 c_1  NA  NA 
+1

伟大的解决方案,这工作完美。增加进度条的现有好处(数据量很大,所以这很有帮助)。谢谢! – avocet