【问题标题】:In R data frame for each set of rows and column use value that is not na在 R 数据框中,每组行和列的使用值不是 na
【发布时间】:2021-01-28 09:55:21
【问题描述】:

我有一个如下结构的数据框 df:

observation  x1  x2  x3  x4
"obs1"         NA  NA  NA  51
"obs1"         NA  NA  NA  NA
"obs1"         NA  25  NA  NA
"obs2"         NA  NA  NA  NA        
"obs2"         NA  NA  NA  NA
"obs2"         NA  NA  NA  56
"obs3"         26  NA  NA  NA
"obs3"         NA  82  NA  NA
"obs3"         NA  NA  "x" NA

我想要一个数据框 df2,对于每个观察和每一列,它都采用一个值,即不是 NA。生成的数据框应如下所示:

observation  x1  x2  x3  x4
"obs1"         NA  25  NA  51
"obs2"         NA  NA  NA  56
"obs3"         26  82  "x" NA

我尝试过:

only_value = function(x){
   x[which(!is.na(x))]
}
df2 = df %>% lapply(only_value) %>% as.data.frame()

但是,这仅适用于每个观察值的数量相同的情况。在我的示例中不是这种情况。

【问题讨论】:

    标签: r function dataframe dplyr


    【解决方案1】:

    使用fcoalescedata.table 选项可能会有所帮助

    type.convert(setDT(df)[,data.table(t(fcoalesce(asplit(.SD,1)))),observation],as.is = TRUE)
    

    给了

       observation x1 x2   x3 x4
    1:        obs1 NA 25 <NA> 51
    2:        obs2 NA NA <NA> 56
    3:        obs3 26 82    x NA
    

    数据

    > dput(df)
    structure(list(observation = c("obs1", "obs1", "obs1", "obs2",
    "obs2", "obs2", "obs3", "obs3", "obs3"), x1 = c(NA, NA, NA, NA,
    NA, NA, 26L, NA, NA), x2 = c(NA, NA, 25L, NA, NA, NA, NA, 82L,
    NA), x3 = c(NA, NA, NA, NA, NA, NA, NA, NA, "x"), x4 = c(51L,
    NA, NA, NA, NA, 56L, NA, NA, NA)), class = "data.frame", row.names = c(NA,
    -9L))
    

    同样,您可以将coalescedplyr 一起使用

    df %>%
      group_by(observation) %>%
      summarise(across(x1:x4,~do.call(coalesce,as.list(.x))))
    

    给了

      observation    x1    x2 x3       x4
    * <chr>       <int> <int> <chr> <int>
    1 obs1           NA    25 <NA>     51
    2 obs2           NA    NA <NA>     56
    3 obs3           26    82 x        NA
    

    【讨论】:

    • 很有趣,谢谢!我认为另一个答案中的代码更容易理解,这就是为什么我会将另一个答案保留为已接受的答案。
    • @MaxJ。不客气。您的用户函数也是一个不错的选择。我只是想提供替代方案来展示其他可能性:)
    【解决方案2】:

    only_value 函数更改为仅返回第一个非 NA 值。

    only_value = function(x){
      x[!is.na(x)][1]
    }
    

    现在按组将此函数应用于列x1x4

    library(dplyr)
    df %>%
      group_by(observation) %>%
      summarise(across(x1:x4, only_value))
    
    # observation    x1    x2 x3       x4
    #* <chr>       <int> <int> <chr> <int>
    #1 obs1           NA    25 NA       51
    #2 obs2           NA    NA NA       56
    #3 obs3           26    82 x        NA
    

    【讨论】:

      猜你喜欢
      • 2023-02-02
      • 2021-01-10
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多