【问题标题】:Fill NAs with numerical sequence by group按组用数字序列填充 NA
【发布时间】:2021-12-18 02:26:59
【问题描述】:

我想按组用数字序列唯一地填充 NA。

这是一个最小的数据集:

d
#>    id year
#> 1   1 1998
#> 2   1 1999
#> 3   1 2001
#> 4   1   NA
#> 5   1   NA
#> 6   2 1997
#> 7   2 1999
#> 8   2 2001
#> 9   2   NA
#> 10  2   NA
#> 11  3 1997
#> 12  3 1998
#> 13  3 1999
#> 14  3 2000
#> 15  3 2001

#data set
structure(list(id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L), year = structure(list(year = c(1997L, 1998L, 
1999L, 2000L, NA, 1998L, 1999L, 2001L, NA, NA, 1998L, 1999L, 
2000L, 2001L, NA)), class = "data.frame", row.names = c(NA, -15L
))), row.names = c(NA, -15L), class = "data.frame")

NAs 应替换为 1997 到 2001 的数字序列的一个未采用的值;这样生成的数据框如下所示:

#>    id year
#> 1   1 1997
#> 2   1 1998
#> 3   1 1999
#> 4   1 2000
#> 5   1 2001
#> 6   2 1997
#> 7   2 1998
#> 8   2 1999
#> 9   2 2000
#> 10  2 2001
#> 11  3 1997
#> 12  3 1998
#> 13  3 1999
#> 14  3 2000
#> 15  3 2001

#data set
structure(list(id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L), year = c(1997L, 1998L, 1999L, 2000L, 2001L, 
1997L, 1998L, 1999L, 2000L, 2001L, 1997L, 1998L, 1999L, 2000L, 
2001L)), class = "data.frame", row.names = c(NA, -15L))

【问题讨论】:

    标签: r dplyr grouping na data-wrangling


    【解决方案1】:

    基础 R 替代方案:

    d$year2 <- ave(d$year, d$id, FUN = function(z) { z[is.na(z)] <- setdiff(1997:2001, z); z;})
    d
    #    id year year2
    # 1   1 1998  1998
    # 2   1 1999  1999
    # 3   1 2001  2001
    # 4   1   NA  1997
    # 5   1   NA  2000
    # 6   2 1997  1997
    # 7   2 1999  1999
    # 8   2 2001  2001
    # 9   2   NA  1998
    # 10  2   NA  2000
    # 11  3 1997  1997
    # 12  3 1998  1998
    # 13  3 1999  1999
    # 14  3 2000  2000
    # 15  3 2001  2001
    

    ave 是一个简单的函数,用于根据分组标准(类似list 的第二个参数)对向量(第一个参数)进行操作。该函数一次被赋予一组值的单个向量,因此使用此数据调用 anon-func 三次。 ave 的唯一问题是 ave 总是将函数的返回值强制为与输入向量相同的类,这可能令人沮丧和荒谬(我确信在某些时候这种行为是有原因的)。

    知道在任何时候z 是所有year 一次一组,该函数的内部工作很简单:用1997:2001 中缺少的值替换所有NA 值。但是,这有一个很大的警告:这假定z 中唯一合法的值是c(NA, 1997:2001);如果还有其他问题,这可能会非常失败/爆炸或导致您邻居的汽车失火。

    从这个意义上说,这种方法有点脆弱。为了更有弹性,我们可能需要一些津贴。例如,是否可以在数据中保留 1997:2001 之外的值,或者也应该替换它们?如果不是,那么是否有一种启发式方法来确定哪些缺失值被归入NA 值?


    数据

    d <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), year = c(1998L, 1999L, 2001L, NA, NA, 1997L, 1999L, 2001L, NA, NA, 1997L, 1998L, 1999L, 2000L, 2001L)), class = "data.frame", row.names = c(NA, -15L))
    

    【讨论】:

    • 尽管我必须承认我并不完全理解代码,但这个答案适用于我的(更复杂的)数据集。谢谢!
    • 我在答案中添加了一个小对话框,希望它能提供一些上下文。
    【解决方案2】:

    我们可能会使用coalesce

    library(dplyr)
    d$year <- coalesce(prodNA(d[2],noNA=0.3)$year, d$year)
    

    如果需要分组

    library(dplyr)
    d %>% 
       group_by(id) %>% 
       mutate(year = coalesce(prodNA(cur_data()["year"], noNA = 0.3)$year, year)) %>%
       ungroup
    

    -输出

    # A tibble: 15 × 2
          id  year
       <int> <int>
     1     1  1997
     2     1  1998
     3     1  1999
     4     1  2000
     5     1  2001
     6     2  1997
     7     2  1998
     8     2  1999
     9     2  2000
    10     2  2001
    11     3  1997
    12     3  1998
    13     3  1999
    14     3  2000
    15     3  2001
    

    数据

    set.seed(1)
    d <- data.frame(id = rep(1:3,each=5),
           year = rep(1997:2001,3))
    

    【讨论】:

    • 我总是忘记这个功能...谢谢!
    • 什么是分组解决方案?
    • @Maël 更新了帖子
    • 谢谢,但它实际上不适用于我的数据集...您使用的是什么数据?
    • @Maël 我更新了我使用的数据。我没有在您的数据中使用d$year&lt;- prodNA(d[2],noNA=0.3); d&lt;-arrange(d,id,year)。原因是您正在使用新的“年份”更新原始数据中的year 列,因此原始“年份”不可用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-27
    • 2015-02-06
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多