在 R 中的数据框中插入带零的行
Insert rows with zeros in data frames in R
考虑这样一个分散的数据集:
ID Date Value
1 1 2012-01-01 5065
4 1 2012-01-04 1508
5 1 2012-01-05 9489
6 1 2012-01-06 7613
7 2 2012-01-07 6896
8 2 2012-01-08 2643
11 3 2012-01-02 7294
12 3 2012-01-03 8726
13 3 2012-01-04 6262
14 3 2012-01-05 2999
15 3 2012-01-06 10000
16 3 2012-01-07 1405
18 3 2012-01-09 8372
请注意 (2,3,9,10,17) 的观测值缺失。我想要的是用 "Value" = 0 来填补数据集中的一些空白,如下所示:
ID Date Value
1 1 2012-01-01 5920
2 1 2012-01-02 0
3 1 2012-01-03 0
4 1 2012-01-04 8377
5 1 2012-01-05 7810
6 1 2012-01-06 6452
7 2 2012-01-07 3483
8 2 2012-01-08 5426
9 2 2012-01-09 0
11 3 2012-01-02 7854
12 3 2012-01-03 1948
13 3 2012-01-04 7141
14 3 2012-01-05 5402
15 3 2012-01-06 6412
16 3 2012-01-07 7043
17 3 2012-01-08 0
18 3 2012-01-09 3270
重点是只有在过去观察到相同(分组)ID 时才应插入零。我想避免任何循环,因为完整的数据集非常大。
有什么建议吗?要重现数据帧:
df <- data.frame(matrix(0, nrow = 18, ncol = 3,
dimnames = list(NULL, c("ID","Date","Value"))) )
df[,1] = c(1,1,1,1,1,1,2,2,2,3,3,3,3,3,3,3,3,3)
df[,2] = seq(as.Date("2012-01-01"),
as.Date("2012-01-9"),
by=1)
df[,3] = sample(1000:10000,18,replace=T)
df = df[-c(2,3,9,10,17),]
Tidyverse 有 complete
,这是扩展类似内容的好方法。我们还可以在同一步骤中使用 fill
参数将 NAs
替换为零。
library(tidyverse)
df %>% group_by(ID) %>%
complete(Date = seq(min(Date), max(Date), "day"), fill = list(Value = 0))
# A tibble: 16 x 3
# Groups: ID [3]
ID Date Value
<dbl> <date> <dbl>
1 1 2012-01-01 1047
2 1 2012-01-02 0
3 1 2012-01-03 0
4 1 2012-01-04 8147
5 1 2012-01-05 1359
6 1 2012-01-06 1892
7 2 2012-01-07 3362
8 2 2012-01-08 8988
9 3 2012-01-02 2731
10 3 2012-01-03 9794
...
以下是基本的 R 解决方案。它使用 split
将输入分成子数据帧,然后 lapply
处理每个子数据帧。
result <- lapply(split(df, df$ID), function(DF){
Date <- seq(min(DF$Date), max(DF$Date), by = "days")
DF2 <- data.frame(ID = rep(DF$ID[1], length.out = length(Date)))
DF2$Date <- Date
DF2$Value <- 0
DF2$Value[Date %in% DF$Date] <- DF$Value
DF2
})
result <- do.call(rbind, result)
row.names(result) <- NULL
result
这里已经有一些可靠的答案,但我建议您查看包 padr
。
library(dplyr)
library(padr)
df %>%
pad(start_val = as.Date("2012-01-01"),
end_val = as.Date("2012-01-09"),
group = "ID") %>%
fill_by_value(Value)
该包还提供了一些非常直观的函数来汇总日期列。
考虑这样一个分散的数据集:
ID Date Value
1 1 2012-01-01 5065
4 1 2012-01-04 1508
5 1 2012-01-05 9489
6 1 2012-01-06 7613
7 2 2012-01-07 6896
8 2 2012-01-08 2643
11 3 2012-01-02 7294
12 3 2012-01-03 8726
13 3 2012-01-04 6262
14 3 2012-01-05 2999
15 3 2012-01-06 10000
16 3 2012-01-07 1405
18 3 2012-01-09 8372
请注意 (2,3,9,10,17) 的观测值缺失。我想要的是用 "Value" = 0 来填补数据集中的一些空白,如下所示:
ID Date Value
1 1 2012-01-01 5920
2 1 2012-01-02 0
3 1 2012-01-03 0
4 1 2012-01-04 8377
5 1 2012-01-05 7810
6 1 2012-01-06 6452
7 2 2012-01-07 3483
8 2 2012-01-08 5426
9 2 2012-01-09 0
11 3 2012-01-02 7854
12 3 2012-01-03 1948
13 3 2012-01-04 7141
14 3 2012-01-05 5402
15 3 2012-01-06 6412
16 3 2012-01-07 7043
17 3 2012-01-08 0
18 3 2012-01-09 3270
重点是只有在过去观察到相同(分组)ID 时才应插入零。我想避免任何循环,因为完整的数据集非常大。
有什么建议吗?要重现数据帧:
df <- data.frame(matrix(0, nrow = 18, ncol = 3,
dimnames = list(NULL, c("ID","Date","Value"))) )
df[,1] = c(1,1,1,1,1,1,2,2,2,3,3,3,3,3,3,3,3,3)
df[,2] = seq(as.Date("2012-01-01"),
as.Date("2012-01-9"),
by=1)
df[,3] = sample(1000:10000,18,replace=T)
df = df[-c(2,3,9,10,17),]
Tidyverse 有 complete
,这是扩展类似内容的好方法。我们还可以在同一步骤中使用 fill
参数将 NAs
替换为零。
library(tidyverse)
df %>% group_by(ID) %>%
complete(Date = seq(min(Date), max(Date), "day"), fill = list(Value = 0))
# A tibble: 16 x 3
# Groups: ID [3]
ID Date Value
<dbl> <date> <dbl>
1 1 2012-01-01 1047
2 1 2012-01-02 0
3 1 2012-01-03 0
4 1 2012-01-04 8147
5 1 2012-01-05 1359
6 1 2012-01-06 1892
7 2 2012-01-07 3362
8 2 2012-01-08 8988
9 3 2012-01-02 2731
10 3 2012-01-03 9794
...
以下是基本的 R 解决方案。它使用 split
将输入分成子数据帧,然后 lapply
处理每个子数据帧。
result <- lapply(split(df, df$ID), function(DF){
Date <- seq(min(DF$Date), max(DF$Date), by = "days")
DF2 <- data.frame(ID = rep(DF$ID[1], length.out = length(Date)))
DF2$Date <- Date
DF2$Value <- 0
DF2$Value[Date %in% DF$Date] <- DF$Value
DF2
})
result <- do.call(rbind, result)
row.names(result) <- NULL
result
这里已经有一些可靠的答案,但我建议您查看包 padr
。
library(dplyr)
library(padr)
df %>%
pad(start_val = as.Date("2012-01-01"),
end_val = as.Date("2012-01-09"),
group = "ID") %>%
fill_by_value(Value)
该包还提供了一些非常直观的函数来汇总日期列。