【问题标题】:collapsing values across row跨行折叠值
【发布时间】:2021-03-17 15:31:10
【问题描述】:

我正在尝试使用 dplyr 函数清理不规则的数据帧。我的意图是逐行评估数据帧,然后附加一个包含该行中所有项目的新列作为列表。我认为列表可能是最好的容器,因为这意味着值可以是任何类型。

library(tidyverse)
col1 <- c("text", NA, "text", NA)
col2 <- c(NA, "text", "text", NA)
col3 <- c("text", NA, "text", NA)
col4 <- c(17, 22, NA, NA)
col5 <- c(3, NA, 3, 17)
df <- data_frame(col1, col2, col3, col4, col5)

df %>% rowwise() %>% mutate(list_col=list(across())) -> out1

此解决方案有效。我添加了一个新列 (list_col),它现在包含列表中的所有值。我接下来的步骤是使用 unlist(没有名称),删除所有 NA 值,然后将所有内容组合回一个整洁的数据框。

但是,为了让我的生活更轻松,我还在运行 mutate 函数时尝试删除所有 NA 值。我尝试使用select 一段时间,直到我意识到select 只计算列名而不是内容。

这就是我要做的。

library(tidyverse)
col1 <- c("text", NA, "text", NA)
col2 <- c(NA, "text", "text", NA)
col3 <- c("text", NA, "text", NA)
col4 <- c(17, 22, NA, NA)
col5 <- c(3, NA, 3, 17)
df <- data_frame(col1, col2, col3, col4, col5)

df %>% rowwise() %>% mutate(list_col=list(!is.na(across()))) -> out2

不幸的是,该行正确运行了所有评估,但随后根据!is.na() 评估将 TRUE/FALSE 值放入列表中。我的问题是:如何更改行,以便 dplyr 现在使用此评估来实际选择数据框的相应条目?

输出:

> print(out2$list_col)
[[1]]
     col1  col2 col3 col4 col5
[1,] TRUE FALSE TRUE TRUE TRUE

[[2]]
      col1 col2  col3 col4  col5
[1,] FALSE TRUE FALSE TRUE FALSE

[[3]]
     col1 col2 col3  col4 col5
[1,] TRUE TRUE TRUE FALSE TRUE

[[4]]
      col1  col2  col3  col4 col5
[1,] FALSE FALSE FALSE FALSE TRUE

期望的输出:

[[1]]
     col1   col3   col4 col5
[1,] "text" "text"  17    3

[[2]]
      col2  col4  
[1,]  "text"  22 

[[3]]
     col1    col2   col3  col5
[1,] "text" "text" "text" 3

[[4]]
      col5
[1,]  17

【问题讨论】:

  • 您想要的输出看起来像 list 的 vector。向量不能有不同的类型
  • 对不起,我是手动写出来的,实际上我无法获得所需的输出。我希望最终能更好地了解输出的实际情况。
  • 你需要list 的lists
  • 我认为这很好。我将使用您给我的选项,看看它会带给我什么。学习的唯一方法就是不断尝试。

标签: r dplyr


【解决方案1】:

在基础 R 中,您可以将 apply 与 na.omit 一起使用:

df$list_col <- apply(df, 1, na.omit)
df
#  col1  col2  col3   col4  col5 list_col 
#  <chr> <chr> <chr> <dbl> <dbl> <list>   
#1 text  NA    text     17     3 <chr [4]>
#2 NA    text  NA       22    NA <chr [2]>
#3 text  text  text     NA     3 <chr [4]>
#4 NA    NA    NA       NA    17 <chr [1]>

【讨论】:

    【解决方案2】:

    我们可以使用pmap

    library(dplyr)
    library(purrr)
    df1 <- df %>%
              mutate(list_col = pmap(., ~ c(na.omit(c(...)))))
    

    -输出

    df1
    # A tibble: 4 x 6
    #  col1  col2  col3   col4  col5 list_col 
    #  <chr> <chr> <chr> <dbl> <dbl> <list>   
    #1 text  <NA>  text     17     3 <chr [4]>
    #2 <NA>  text  <NA>     22    NA <chr [2]>
    #3 text  text  text     NA     3 <chr [4]>
    #4 <NA>  <NA>  <NA>     NA    17 <chr [1]>
    

    或者,如果我们想将across 与is.na 一起使用,请确保使用来自is.na 的逻辑索引对值进行子集化

     df %>% 
         mutate(across(everything(), as.character)) %>%
         rowwise() %>% 
         mutate(list_col=list(across()[!is.na(across())]))
    # A tibble: 4 x 6
    # Rowwise: 
    #  col1  col2  col3  col4  col5  list_col 
    #  <chr> <chr> <chr> <chr> <chr> <list>   
    #1 text  <NA>  text  17    3     <chr [4]>
    #2 <NA>  text  <NA>  22    <NA>  <chr [2]>
    #3 text  text  text  <NA>  3     <chr [4]>
    #4 <NA>  <NA>  <NA>  <NA>  17    <chr [1]>
    

    或者另一个选项是base R

    df$list_col <- apply(df, 1, FUN = function(x) x[complete.cases(x)])
     
    

    【讨论】:

    • 啊,谢谢!我弄错了子集,没有意识到我可以将 [ ] 语法与across() 一起使用。我还将探索您发布的其他选项,以更好地理解其他一些命令。
    猜你喜欢
    • 2020-06-03
    • 2017-10-22
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 2021-04-08
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多