【问题标题】:Fill NA values with sequence by group按组按顺序填充 NA 值
【发布时间】:2018-03-29 18:10:34
【问题描述】:

我正在尝试在数据集中填充一些值。我的数据的简化版本可以在下面找到:

    > example_df
           Date    GROUP   value
157     2018-01-31 10180  3.464
158     2018-02-28 10180  3.413
159     2018-03-31 10180  3.418
160     2018-04-30 10180     NA
161     2018-05-31 10180     NA
162     2018-06-30 10180     NA
163     2018-07-31 10180     NA
164     2018-08-31 10180     NA
165     2018-09-30 10180     NA
166     2018-10-31 10180     NA
167     2018-11-30 10180     NA
168     2018-12-31 10180     NA
169     2019-01-31 10180     NA
170     2019-02-28 10180     NA
171     2019-03-31 10180     NA
172     2019-04-30 10180     NA
173     2019-05-31 10180     NA
174     2019-06-30 10180     NA
175     2019-07-31 10180     NA
176     2019-08-31 10180     NA
177     2019-09-30 10180     NA
178     2019-10-31 10180     NA
179     2019-11-30 10180     NA
373     2018-01-31 10420  5.085
374     2018-02-28 10420  5.051
375     2018-03-31 10420  4.993
376     2018-04-30 10420     NA
377     2018-05-31 10420     NA
378     2018-06-30 10420     NA
379     2018-07-31 10420     NA
380     2018-08-31 10420     NA
381     2018-09-30 10420     NA
382     2018-10-31 10420     NA
383     2018-11-30 10420     NA
384     2018-12-31 10420     NA
385     2019-01-31 10420     NA
386     2019-02-28 10420     NA
387     2019-03-31 10420     NA
388     2019-04-30 10420     NA
389     2019-05-31 10420     NA
390     2019-06-30 10420     NA
391     2019-07-31 10420     NA
392     2019-08-31 10420     NA
393     2019-09-30 10420     NA
394     2019-10-31 10420     NA
395     2019-11-30 10420     NA
589     2018-01-31 10500  5.796
590     2018-02-28 10500  5.860
591     2018-03-31 10500  5.913
592     2018-04-30 10500     NA
593     2018-05-31 10500     NA
594     2018-06-30 10500     NA
595     2018-07-31 10500     NA
596     2018-08-31 10500     NA
597     2018-09-30 10500     NA
598     2018-10-31 10500     NA
599     2018-11-30 10500     NA
600     2018-12-31 10500     NA
601     2019-01-31 10500     NA
602     2019-02-28 10500     NA
603     2019-03-31 10500     NA
604     2019-04-30 10500     NA
605     2019-05-31 10500     NA
606     2019-06-30 10500     NA
607     2019-07-31 10500     NA
608     2019-08-31 10500     NA
609     2019-09-30 10500     NA
610     2019-10-31 10500     NA
611     2019-11-30 10500     NA

如您所见。对于每个组,我都有截至今天月份的值,然后是一组 NA,直到下一组开始。我想要做的是,对于每个组,用一个源自最后一个非 NULL 值的序列填充这些 NA,并增加一个固定值(我选择了 0.065),直到该组的最终日期。我更喜欢 dplyr 解决方案,但任何有关如何实现这一点的信息都会非常有帮助。谢谢。

【问题讨论】:

标签: r dplyr data.table


【解决方案1】:
library(data.table)
dt = as.data.table(yourdf) # or convert in place using setDT

dt[, value := value[1] + 0.065 * (1:.N - 1)
   , by = .(GROUP, cumsum(!is.na(value)))]

【讨论】:

  • 嗨@eddi 感谢您的帮助,这是完美的。你对做这种同样的操作有什么建议,但不是增加一个固定值,而是在 n 个月内增加“x”个百分比?例如,在 18 个月内增加了 10%。
  • seq,类似于DF[, v := seq(first(value), by=0.065, length.out=.N), by=.(GROUP, rleid(GROUP, cumsum(!is.na(value))))]
  • @JustinKlevs 我有点不清楚你的意思 - 也许按照弗兰克的建议使用seq,而不是by,设置最终值?
  • 嗨@eddi。谢谢你的建议。参考您之前关于百分比增加的建议。我的想法略有不同。不是为序列中的每个观察值增加 10%,而是在设定的月数或存在 NA 的总期间内总共增加 10%。所有这些信息都非常有价值,谢谢
  • @JustinKlevs seq(first(value), first(value)*1.1, length.out=.N)n() 而不是 .N 如果您使用的是 dplyr 而不是 data.table。您可以阅读?seq 了解许多变化。
【解决方案2】:

你可以做这样的事情(受 Frank 和 eddi 的 cmets/solutions 启发):

df$value2 <- ave(df$value, df$GROUP, cumsum(!is.na(df$value)),
                 FUN = function(x) x[1] + 0.065 * (1:length(x) - 1))

或者我原来的ave

df$value2 <- ave(df$value, df$GROUP, 
                 FUN = function(x) {nas_to_replace <- is.na(x) & seq_along(x) > tail(which(!is.na(x)),1)
                                    replace(x,  nas_to_replace, 
                                                tail(x[!is.na(x)],1) + 0.065*(1:sum(nas_to_replace)))} )

此函数旨在仅替换最后一个非 NA 之后的 NA。所以如果你有一个像c(NA, 1, 2, NA, NA) 这样的向量,它只会替换最后两个元素。

head(df)
#      Date GROUP value value2
#1 2018-01-31 10180 3.464  3.464
#2 2018-02-28 10180 3.413  3.413
#3 2018-03-31 10180 3.418  3.418
#4 2018-04-30 10180    NA  3.483
#5 2018-05-31 10180    NA  3.548
#6 2018-06-30 10180    NA  3.613

【讨论】:

    【解决方案3】:

    不像data.table 解决方案那样优雅,但使用dplyr 并在此answer 的基础上构建,您可以执行以下操作:

    library(dplyr)
    df %>% 
      group_by(GROUP, tmp=cumsum(!is.na(value))) %>%
      mutate(value=value[1] + 0.065*(0:(length(value)-1))) %>% 
      ungroup() %>% 
      select(-tmp)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-18
      • 1970-01-01
      • 2015-02-06
      • 1970-01-01
      • 2017-10-06
      • 1970-01-01
      • 2022-01-27
      相关资源
      最近更新 更多