【问题标题】:Fill in missing rows in R data frame填充 R 数据框中缺失的行
【发布时间】:2019-03-08 13:35:54
【问题描述】:

我已经将一些原始数据导入到 R 中,如下所示:

表1:

ID    Year    Value
01    1999       25
01    2000       12
01    2002       14
02    1998       16
02    2003        0
02    2004       14

该表按 ID 和年份排序,但如您所见,缺少一些年份。我从数据来源知道这些缺失年份的价值应该为零。我有另一个变量,我称之为 MODEL_YEAR,并设置为 2015。我想填补空白,包括 MODEL_YEAR。

我认为我会采取的步骤是:

  1. 为表 1 中的每个 ID 选择最早的年份。
  2. 构建一个新表(Table2),其中包含从每个 ID 的最早年份到 MODEL_YEAR 的连续年份。
  3. 将 Table1 连接到 Table2 以重新添加值,并将任何 NA 值替换为零。

我认为我可以完成第 1 步和第 3 步,但无法弄清楚如何进行第 2 步,即构建 Table2。

如果您认为我的方法不是最佳的,我们将不胜感激任何帮助或替代方法的建议。

谢谢

【问题讨论】:

  • 如果我没记错的话,您想使用2015 作为去年,但第一个呢?
  • 第一个因 ID 而异 - 这就是为什么在第 1 步中我想为每个 ID 选择第一年。

标签: r data-manipulation


【解决方案1】:

我认为tidyr::expand() 会很有用。这是tidyverse 解决方案:

library(tidyverse)
# how to build table2
table2 <- table1 %>% group_by(ID) %>% mutate(Earliest.Year = min(Year)) %>%
        select(-Value, -Year) %>% distinct() %>%
        expand(Year = Earliest.Year:2015, Earliest.Year) %>%
        select(-Earliest.Year)

# a direct piepe solution
table1 %>% group_by(ID) %>% mutate(Earliest.Year = min(Year)) %>%
        select(-Value, -Year) %>% distinct() %>%
        expand(Year = Earliest.Year:2015, Earliest.Year) %>%
        select(-Earliest.Year) %>%
        left_join(table1, by = c("ID", "Year")) %>%
        replace(is.na(.), 0)
# output
# A tibble: 35 x 3
# Groups:   ID [?]
      ID  Year Value
   <int> <int> <dbl>
 1     1  1999    25
 2     1  2000    12
 3     1  2001     0
 4     1  2002    14
 5     1  2003     0
 6     1  2004     0
 7     1  2005     0
 8     1  2006     0
 9     1  2007     0
10     1  2008     0
# ... with 25 more rows

【讨论】:

  • 谢谢。这适用于我提供的示例数据。出于某种原因,当我尝试对我的实际数据使用“扩展”时,我收到消息“警告消息:在 status2$srdd:MODEL_YEAR 中:数值表达式有 13068083 个元素:仅使用第一个元素”。不知道为什么会发生这种情况,正在努力解决...
  • 此警告消息指出您有一整列 13068083 个值 2015(即 status2$MODEL_YEAR),但仅使用此列的第一个值。由于第一个值是 2015 一切都应该没问题,但您可以通过将 MODEL_YEAR 设置为长度为 1 (MODEL_YEAR &lt;- 2015) 的向量而不是数据框中的变量来避免此警告消息
【解决方案2】:

由于tidyr::expand() 已被占用,与tidyr::complete 的解决方案略有不同:

library(tidyverse)

dat %>%
  bind_rows(
    mutate(dat, Year = 2015, Value = 0) %>% unique()
  ) %>%
  group_by(ID) %>%                           # allows to start from earliest year
  complete(Year = full_seq(Year, 1), ID) %>% # expand years up 2 2015 for each ID
  mutate(Value = coalesce(Value, 0)) %>%     # fill NAs by zeros
  ungroup()  

哪些输出:

# A tibble: 35 x 3
    Year ID    Value
   <dbl> <chr> <dbl>
 1  1999 01       25
 2  2000 01       12
 3  2001 01        0
 4  2002 01       14
 5  2003 01        0
 6  2004 01        0
 7  2005 01        0
 8  2006 01        0
 9  2007 01        0
10  2008 01        0
# ... with 25 more rows

我使用的数据:

dat <- read.table(
  text = "ID    Year    Value
          01    1999       25
          01    2000       12
          01    2002       14
          02    1998       16
          02    2003        0
          02    2004       14",
  header = T,
  colClasses = c("character", "integer", "integer")
)

【讨论】:

  • 关于"ID = c("01", "02")"这一行——我的实际数据有数千个ID——有没有办法在不命名它们的情况下做到这一点?
  • 最简单的应该是ID = unique(dat$ID)ID = unique(.$ID)
【解决方案3】:

1) Base R 使用bytable1 拆分为ID 并将每个组件rbind 拆分为具有相同ID 的数据框,每个所需的@987654326 @ 和 Value 为 0。然后使用 sum 聚合,最后使用 rbind 将组件重新组合在一起。

do.call("rbind", by(table1, table1$ID, function(x) {
  r <- rbind(x, data.frame(ID = x$ID[1], Year = x$Year[1]:MODEL_YEAR, Value = 0))
  aggregate(Value ~ ID + Year, r, sum)
}))

给予:

     ID Year Value
1.1   1 1999    25
1.2   1 2000    12
1.3   1 2001     0
1.4   1 2002    14
1.5   1 2003     0
1.6   1 2004     0
1.7   1 2005     0
...etc...

2) dplyr 这使用相同的方法但被翻译为使用 dplyr。

library(dplyr)

table1 %>%
 group_by(ID) %>%
 do(bind_rows(., data.frame(ID = .$ID[1], Year = .$Year[1]:MODEL_YEAR, Value = 0))) %>%
 group_by(Year, add = TRUE) %>%
 summarize(Value = sum(Value)) %>%
 ungroup

注意

table1 是可重现的形式:

table1 <-
structure(list(ID = c(1L, 1L, 1L, 2L, 2L, 2L), Year = c(1999L, 
2000L, 2002L, 1998L, 2003L, 2004L), Value = c(25L, 12L, 14L, 
16L, 0L, 14L)), class = "data.frame", row.names = c(NA, -6L))

MODEL_YEAR <- 2015

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-14
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 2019-05-16
    • 2018-03-22
    相关资源
    最近更新 更多