【问题标题】:Combine multiple columns into vector by row with dplyr使用 dplyr 将多列逐行组合成向量
【发布时间】:2020-03-10 20:25:00
【问题描述】:

我正在尝试将多列合并到每一行的单个单元格中,然后删除缺失值。

样本数据:

df <- data.frame(a=c("a", "b", "c", "d"),
                 b=c(NA, "a", "b", "c"),
                 c=c("a", "b", "e", "g"))

尝试:

df %>% rowwise() %>%
mutate(collapse=as.character(paste(a,b,c, collapse=",")),
       collapse_nona=na.omit(collapse))

输出:

# A tibble: 4 x 5
  a     b     c     collapse                collapse_nona         
* <fct> <fct> <fct> <chr>                   <chr>                 
1 a     NA    a     a NA a,b a b,c b e,d c… a NA a,b a b,c b e,d …
2 b     a     b     a NA a,b a b,c b e,d c… a NA a,b a b,c b e,d …
3 c     b     e     a NA a,b a b,c b e,d c… a NA a,b a b,c b e,d …
4 d     c     g     a NA a,b a b,c b e,d c… a NA a,b a b,c b e,d …

1) 我没有成功地为每一行创建具有值的单元格(整列出现在折叠中)。

2) 折叠列中的单元格的行为不像向量。

期望的输出

  a     b     c     collapse                collapse_nona         
* <fct> <fct> <fct> <chr>                   <chr>                 
1 a     NA    a     a NA a                  a a
2 b     a     b     b a b                   b a b
3 c     b     e     c b e                   c b e
4 d     c     g     d c g                   d c g

谢谢

【问题讨论】:

  • 试试unite df %&gt;% mutate_all(as.character) %&gt;% unite(collapse, a, b,c, na.rm = TRUE, remove = FALSE, sep=" ")

标签: r dplyr


【解决方案1】:

unite 有一个na.rm 选项,默认为 FALSE

library(tidyr)
library(dplyr)
df %>%
   mutate_all(as.character) %>%
   unite(collapse, a, b,c,  remove = FALSE, sep=" ") %>%
   unite(collapse_nona, a, b, c, remove = FALSE, sep=" ", na.rm = TRUE) %>%
   select(names(df), everything())
#   a    b c collapse collapse_nona
#1 a <NA> a   a NA a           a a
#2 b    a b    b a b         b a b
#3 c    b e    c b e         c b e
#4 d    c g    d c g         d c g

或者使用pastestr_remove_all(来自stringr) - 请注意paste/str_c 是矢量化的,因此无需使用rowwise 循环遍历每一行

df %>%
     mutate(collapse = paste(a, b, c), 
            collapse_nona = str_remove_all(collapse,  "\\sNA|NA\\s"))
#  a    b c collapse collapse_nona
#1 a <NA> a   a NA a           a a
#2 b    a b    b a b         b a b
#3 c    b e    c b e         c b e
#4 d    c g    d c g         d c g

另一个选项是 pmap 循环遍历每一行,删除 NA 元素与 na.omit 然后 pastestr_c(来自 stringr

library(dplyr)
library(stringr)
library(purrr)
df %>%
     mutate_all(as.character) %>% 
     mutate(collapse_nona = pmap_chr(., ~ c(...) %>%
                na.omit %>%
                str_c(collapse=" "))) 
#  a    b c collapse_nona
#1 a <NA> a           a a
#2 b    a b         b a b
#3 c    b e         c b e
#4 d    c g         d c g

【讨论】:

  • 关于在collapse_nona 中标记具有不相同条目的单元格有什么建议吗?所以第 2,3&4 行被标记,因为并非所有条目都相同。
  • @EML 你的第二行有两个'b'元素
  • @EML 你需要df %&gt;% mutate_all(as.character) %&gt;% mutate(flag = pmap_lgl(., ~ n_distinct(na.omit(c(...))) &gt; 1) )
  • 我的意思是,如果至少有一个元素不同,则该行被标记。
  • @EML 好的,在这种情况下,注释中的代码应该可以工作
【解决方案2】:

认为核心问题是你不想要collapse,你想要sep。然后不需要按行计算。此外,NA 将被打印为字符,因此您无法使用 na.omit 删除它们

df %>% 
   mutate(collapse = paste(a,b,c, sep = " "), collapse_nona = gsub("NA", "", collapse))

  a    b c collapse collapse_nona
1 a <NA> a   a NA a          a  a
2 b    a b    b a b         b a b
3 c    b e    c b e         c b e
4 d    c g    d c g         d c g

【讨论】:

    【解决方案3】:

    我认为这样做。您可以在 str_c 中使用 sep 参数。

    library(dplyr)
    library(stringr)
    df %>% 
      mutate(collapse = str_c(str_replace_na(a), str_replace_na(b), str_replace_na(c), sep = " "),
             collapse_nona = str_c(str_replace_na(a, ""), str_replace_na(b, ""), str_replace_na(c,""), sep = " "))
    
      a    b c collapse collapse_nona
    1 a <NA> a   a NA a          a  a
    2 b    a b    b a b         b a b
    3 c    b e    c b e         c b e
    4 d    c g    d c g         d c g
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-31
      • 2021-05-31
      • 1970-01-01
      • 1970-01-01
      • 2017-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多