展开然后填充数据框

Expand and then fill a dataframe

我有关于 2014 年到 2021 年 8 年 属性 租金价格的不完整数据。我想扩展到一个完整的面板,以便每年每个 属性 都有一个值这些年。这是通过将价值从一年转移到另一年来完成的。目前每个 属性 都是数据帧列表中的一个条目。此 R 代码创建一些虚拟数据 (df1、df2、df3) 并给出我正在寻找的结果 (df4)。

year <- c(2014, 2019, 2021)
price <- c(100, 110, 120)
df1 <- data.frame(cbind(id=1, year, price))

year <- c(2016, 2019, 2021)
price <- c(200, 210, 220)
df2 <- data.frame(cbind(id=2, year, price))

year <-c (2014, 2015, 2019, 2020)
price <-c (300, 310, 320, 330)
df3 <- data.frame(cbind(id=3, year, price))

list1 <- list(df1, df2, df3)

id <- c(rep(1,8), rep(2,8), rep(3,8))
year <- c(rep(seq(2014,2021), 3))
price <- c(100, 100, 100, 100, 100, 110, 110, 120,
           200, 200, 200, 200, 200, 210, 210, 220,
           300, 310, 310, 310, 310, 320, 330, 330)
df4 <- data.frame(id, year, price)

所以对于 属性 id=1,我有 2014 年、2019 年和 2021 年的数据。我将使用 2014 年的价格向前填充 2015 年至 2018 年。对于 属性 id=2 我将用 2016 回填 2014 和 2015,并用 2016 回填 2017 到 2018。

我可以通过重新绑定列表中的所有数据框,然后将其与包含所有 id by year 组合的新数据框合并来开始。但这不会完成我想要的填充,所有缺失的 id by year 组合都将是 NA。

我总共有大约 100,000 个属性可以执行此任务。谢谢

通过tidyverse查看fill()函数功能。

使用您的示例,但归纳出您提到的 NA,df5 应该是您在这里寻找的内容。

library( tidyverse )
year <- c(2014, 2019, 2021)
price <- c(100, 110, 120)
df1 <- data.frame(cbind(id=1, year, price))

year <- c(2016, 2019, 2021)
price <- c(200, 210, 220)
df2 <- data.frame(cbind(id=2, year, price))

year <-c (2014, 2015, 2019, 2020)
price <-c (300, 310, 320, 330)
df3 <- data.frame(cbind(id=3, year, price))

list1 <- list(df1, df2, df3)

id <- c(rep(1,8), rep(2,8), rep(3,8))
year <- c(rep(seq(2014,2021), 3))
price <- c(100, NA, NA, NA, NA, 110, NA, 120,
           NA, NA, 200, NA, NA, 210, 210, 220,
           300, 310, 310, 310, 310, 320, 330, 330)
df4 <- data.frame(id, year, price)
df5 <- df4 %>% group_by( id ) %>% fill( price, .direction = "downup" )

或者用purrr

years <- tibble(year = c(2014:2021))

list1 %>% 
  map_dfr(~.x %>% 
        right_join(years, by = "year") %>% 
        arrange(year) %>% 
        fill(id, .direction = "down") %>% 
        fill(id, .direction = "up") %>% 
        fill(price, .direction = "downup"))