【问题标题】:Populate the missing values from a variable with values from the closest point in time, in R用 R 中最近时间点的值填充变量中的缺失值
【发布时间】:2020-01-07 23:23:35
【问题描述】:

我的数据看起来像这样(但针对 1400 万人)

它是每个人在给定季度 (qtr) 中的 MB 值。如果 qtr == 20091001,则为 2009 年 10 月至 2009 年 12 月期间。

df <- data.frame(
  ID = rep(c('ABC1234', 'CED6723', 'GHB9876', "MNR4444", "FRE9823"), 4),
  qtr = c(rep('20090101', 5), rep('20090401', 5),rep('20090701', 5),rep('20091001', 5)),
  MB = c('0000000', "1234567", "5678910", "1234567", 
         "9384756", "3456789", NA, '0000000',
         "7394857", '0000000', '0000000', '0000000',
         "9485967", "9485967", "9485967", '0000000',
         '0000000', NA, '4545455', '1987656'
         )
)

我想要做的是用最新的 MB 值替换 MB 的值,它是 NA 或 == '0000000'。

规则是: 如果 MB 在 20091001 中为 NA 或 0,我希望该值来自 20090701(如果已填充),然后是 20090401(如果已填充),然后是 20090101。

如果 MB 在 20090701 中为 NA 或 0,我希望该值来自 20090401(如果已填充),然后是 20090101(如果已填充),然后是 20091001。

如果 MB 在 20090401 中为 NA 或 0,我希望该值来自 20090101(如果已填充),然后是 20090701(如果已填充),然后是 20091001。

如果 MB 在 20090101 中为 NA 或 0,我希望该值来自 20090401(如果已填充),然后是 20090701(如果已填充),然后是 20091001。

我的理想输出是这样的

df2 <- data.frame(
  ID = rep(c('ABC1234', 'CED6723', 'GHB9876', "MNR4444", "FRE9823"), 4),
  qtr = c(rep('20090101', 5), rep('20090401', 5),rep('20090701', 5),rep('20091001', 5)),
  MB = c("1234567", "1234567", "5678910", "1234567", 
         "9384756", "3456789", "3456789", "3456789",
         "7394857", "7394857", "7394857", "7394857",
         "9485967", "9485967", "9485967", "9485967",
         '4545455', '4545455', '4545455', '1987656'
  )
)

我看到了这个回复r - copy missing values from other variables 这适用于宽格式的数据。我是否需要将我的数据转换为宽格式,并将 qtr 变量的标签更改为 1、2、3、4 ?或者有没有办法在我的数据框上做到这一点?

谢谢。

【问题讨论】:

  • 根据您的描述,听起来您正在从过去(如果有)和未来提取数据。这是故意的吗?
  • 你想为每个ID做这个吗?
  • 是的,如果过去不可用,则从未来提取数据。是的,我想为任何有 NA 或任何季度值的 ID 执行此操作。谢谢。

标签: r group-by dplyr time-series


【解决方案1】:

所以你可以通过使用 tidyr 函数填充来做到这一点,但首先我检查了该值是否为零,然后我将其设为 NA,因为填充仅关注 NA 值,如下所示;

library(dplyr)
library(tidyr)

# Creating dataframe
df <- data.frame(
  ID = rep(c('ABC1234', 'CED6723', 'GHB9876', "MNR4444", "FRE9823"), 4),
  qtr = c(rep('20090101', 5), rep('20090401', 5),rep('20090701', 5),rep('20091001', 5)),
  MB = c('0000000', "1234567", "5678910", "1234567", 
         "9384756", "3456789", NA, '0000000',
         "7394857", '0000000', '0000000', '0000000',
         "9485967", "9485967", "9485967", '0000000',
         '0000000', NA, '4545455', '1987656'),
  stringsAsFactors = FALSE
)

df2 <-
  df %>%
  # If MB is zeros then convert it into NA
  mutate(MB = ifelse(as.numeric(MB) == 0, NA_character_, MB)) %>%
  # Fill automatically fills NA data with closest values
  # given the direction of the filling
  # you can change the direction as you like
  # To know more about it ?fill
  fill(MB, .direction = "downup")

df2

# ID      qtr      MB
# ABC1234 20090101 1234567
# CED6723 20090101 1234567
# GHB9876 20090101 5678910
# MNR4444 20090101 1234567
# FRE9823 20090101 9384756
# ABC1234 20090401 3456789
# CED6723 20090401 3456789
# GHB9876 20090401 3456789
# MNR4444 20090401 7394857
# FRE9823 20090401 7394857

【讨论】:

  • 我认为您需要添加group_by(ID) 以使填充特定于个人。
  • @Ronak 实际上你是正确的,输出与预期的输出相差甚远。我认为这个想法并不适用于每个 ID。我删除了 group_by 代码行。
【解决方案2】:

我们可以使用zoo::na.locf,假设数据按qtr排序,如共享数据所示。

df$MB <- as.numeric(as.character(df$MB))
df$MB <- replace(df$MB, df$MB == 0, NA)
df$MB <- zoo::na.locf(df$MB, fromLast = TRUE)

df
#        ID      qtr      MB
#1  ABC1234 20090101 1234567
#2  CED6723 20090101 1234567
#3  GHB9876 20090101 5678910
#4  MNR4444 20090101 1234567
#5  FRE9823 20090101 9384756
#6  ABC1234 20090401 3456789
#7  CED6723 20090401 7394857
#8  GHB9876 20090401 7394857
#9  MNR4444 20090401 7394857
#10 FRE9823 20090401 9485967
#11 ABC1234 20090701 9485967
#12 CED6723 20090701 9485967
#13 GHB9876 20090701 9485967
#14 MNR4444 20090701 9485967
#15 FRE9823 20090701 9485967
#16 ABC1234 20091001 4545455
#17 CED6723 20091001 4545455
#18 GHB9876 20091001 4545455
#19 MNR4444 20091001 4545455
#20 FRE9823 20091001 1987656

【讨论】:

  • 谢谢罗纳克。这似乎不适用于我更大的数据集。我不认为代码对个人来说是明确的。所以一个人的信息被添加到另一个人的信息上。有没有办法更改此代码,以便仅在 ID 值匹配时替换缺失值?
  • @Laura 您的预期输出并未显示这必须由ID 应用。例如,对于ID“ABC1234”,您如何将MB 值作为1234567。之前的 ID 没有任何价值。
  • 谢谢@Ronak。对于 ID ABC1234,我希望 MB 的值来​​自稍后的时间。所以我们先在时间上向后看,但是如果没有合适的匹配,那么我们就开始在时间上向前看。这可能吗?
  • @Laura 如果您稍后及时查看 ID ABC1234,后面的值是 3456789 而不是 1234567。您可以尝试df %&gt;% mutate(MB = as.numeric(as.character(MB)), MB = replace(MB, MB == 0, NA)) %&gt;% arrange(ID, qtr) %&gt;% group_by(ID) %&gt;% fill(MB, .direction = "updown")
猜你喜欢
  • 2019-11-18
  • 2019-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-03
  • 2016-12-08
相关资源
最近更新 更多