【问题标题】:How to replace NaN value with previous non-NaN within group如何用组内以前的非 NaN 替换 NaN 值
【发布时间】:2018-11-08 14:55:59
【问题描述】:

我需要用组中以前的非 NaN 值替换 NaN 值。

这是一个例子:

+-------+------------+-------+
| ts_id |    date    | value |
+-------+------------+-------+
|     2 | 01/10/2014 | 18    |
|     2 | 01/11/2014 | 15    |
|     2 | 01/12/2014 | NaN   |
|     2 | 01/01/2015 | NaN   |
|     2 | 01/02/2015 | NaN   |
|     3 | 01/03/2015 | 19    |
|     3 | 01/04/2015 | 20    |
|     3 | 01/10/2015 | 12    |
|     3 | 01/11/2015 | 17    |
|     3 | 01/12/2015 | NaN   |
|     3 | 01/01/2016 | NaN   |
|     3 | 01/08/2016 | 7     |
|     3 | 01/09/2016 | NaN   |
|     3 | 01/10/2016 | NaN   |
|     3 | 01/11/2016 | NaN   |
|     3 | 01/12/2016 | NaN   |
|     3 | 01/01/2017 | NaN   |
+-------+------------+-------+

数据:

data <- structure(list(ts_id = c(2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 
                         3, 3, 3, 3, 3), date = structure(c(16344, 16375, 16405, 16436, 
                                                            16467, 16495, 16526, 16709, 16740, 16770, 16801, 17014, 17045, 
                                                            17075, 17106, 17136, 17167), class = "Date"), value = c(18, 15, 
                                                                                                                    NaN, NaN, NaN, 19, 20, 12, 17, NaN, NaN, 7, NaN, NaN, NaN, NaN, 
                                                                                                                    NaN)), row.names = c(NA, -17L), vars = "ts_id", drop = TRUE, indices = list(
                                                                                                                      0:16), group_sizes = 17L, biggest_group_size = 17L, labels = structure(list(
                                                                                                                        ts_id = 3L), row.names = c(NA, -1L), class = "data.frame", vars = "ts_id", drop = TRUE), class = "data.frame")

在每个组中(由 ts_id 标识),我可以在任何给定日期拥有 NaN 值。我需要用最近的非 NaN 值替换每个 NaN。

结果应如下所示:

+-------+------------+-------+
| ts_id |    date    | value |
+-------+------------+-------+
|     2 | 01/10/2014 |    18 |
|     2 | 01/11/2014 |    15 |
|     2 | 01/12/2014 |    15 |
|     2 | 01/01/2015 |    15 |
|     2 | 01/02/2015 |    15 |
|     3 | 01/03/2015 |    19 |
|     3 | 01/04/2015 |    20 |
|     3 | 01/10/2015 |    12 |
|     3 | 01/11/2015 |    17 |
|     3 | 01/12/2015 |    17 |
|     3 | 01/01/2016 |    17 |
|     3 | 01/08/2016 |     7 |
|     3 | 01/09/2016 |     7 |
|     3 | 01/10/2016 |     7 |
|     3 | 01/11/2016 |     7 |
|     3 | 01/12/2016 |     7 |
|     3 | 01/01/2017 |     7 |
+-------+------------+-------+

提前致谢。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    你可以用这个:

    library(dplyr)
    library(zoo) # for the na.locf function
    data %>% 
      group_by(ts_id) %>% # group by id
      mutate(value = na.locf(value,na.rm=F)) # na.locf fills with the last non-empty value
    
    #head()
    # # A tibble: 6 x 3
    # # Groups:   ts_id [2]
    # ts_id date       value
    # <dbl> <date>     <dbl>
    # 1     2 2014-10-01    18
    # 2     2 2014-11-01    15
    # 3     2 2014-12-01    15
    # 4     2 2015-01-01    15
    # 5     2 2015-02-01    15
    # 6     3 2015-03-01    19
    

    【讨论】:

    • 我不知道na.locf 也适用于NaN。或者(将其全部保留在“诗句”中)然后library(tidyverse); data %&gt;% group_by(ts_id) %&gt;% mutate(value = replace(value, is.nan(value), NA)) %&gt;% fill(value)
    • 我认为您也应该将其添加为答案。
    • 仅供参考,我认为它仍然有效,因为在 na.locf 内部使用 is.na(),它仍然为 NaN 提供 TRUE
    • 有道理
    【解决方案2】:

    遵循与na.locf 相同的逻辑,但将其保留在“诗句中,我们可以做到”,

    library(tidyverse)
    
    data %>% 
      group_by(ts_id) %>% 
      mutate(value = replace(value, is.nan(value), NA)) %>% 
      fill(value) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-14
      • 2012-03-21
      • 2013-06-18
      • 2018-09-24
      • 2012-06-13
      • 1970-01-01
      • 2019-09-29
      相关资源
      最近更新 更多