【问题标题】:Merge 3 columns based on unique values?根据唯一值合并 3 列?
【发布时间】:2019-03-26 18:07:04
【问题描述】:

我正在尝试将 3 列合并为一列。列值用“;”分隔并且新列需要解压缩所有 3 列值并放置唯一值。我知道如何执行合并列。但我正在努力解压缩 3 列中的行值并找到唯一值并放入另一列。

这是虚拟数据

n = c(2, 3, 5,10) 
s = c("aa;bb;cc", "bb;dd;aa", "NA","xx;nn") 
b = c("aa;bb;cc", "bb;dd;cc", "zz;bb;yy","NA") 
t = c("aa;bb;cc", "bb;dd", "kk","NA") 
df = data.frame(n, s, b,t)

> df
   n        s        b        t
1  2 aa;bb;cc aa;bb;cc aa;bb;cc
2  3 bb;dd;aa bb;dd;cc    bb;dd
3  5       NA zz;bb;yy       kk
4 10    xx;nn       NA       NA

预期的输出是

> df
   n  finalcol
1  2 aa;bb;cc
2  3 bb;dd;aa;cc
3  5 zz;bb;yy;kk
4 10 xx;nn

我必须执行一个简单的合并

dff = df %>% unite(finalcol, c(s,b,t), sep = ";", remove = TRUE)

【问题讨论】:

  • apply(df[-1], 1, function(x) paste(unique(unlist(strsplit(x[!is.na(x)], ";"))), collapse = ";"))
  • 感谢@d.b 加入。这里甚至包括 NA,而不是作为新列的一部分。我能做什么?
  • 弄清楚您是否拥有NA"NA"。 cmets 中的答案仅适用于NA

标签: r dataframe merge dplyr tidyr


【解决方案1】:

既然你提到了unite,我想展示一个使用separate 的解决方案,unite 的补充。

此解决方案将其保留在 tidyverse 中,这使得逐步了解正在发生的事情变得容易。 @d.b 在评论中的回答完美,紧凑,可能运行得更快,但学习曲线更陡峭,以了解正在发生的事情。使用管道tidyverse 解决方案,您可以运行每一行并查看发生了什么。

这个解决方案先separates 条款,然后用gather将数据从宽数据格式转换为长数据格式,这样我们就可以进行诸如检查和处理NAs和“NA”s,drop_na等操作,然后distinct,仅获取唯一值(每个组具有相同的“id”,即来自同一原始行的项目)。然后,它使用summarisepaste 回到原始格式,但也可以使用spread 然后unite。 (注意na.rm=TRUEunitehttps://github.com/tidyverse/tidyr/issues/203即将推出的功能)

来源:我使用了这些方便的 dplyrtidyr 参考表: https://github.com/rstudio/cheatsheets/raw/master/data-transformation.pdf https://github.com/rstudio/cheatsheets/raw/master/data-import.pdf 并且我还根据这里的 cmets、问题和答案制定了解决方案:How do I remove NAs with the tidyr::unite function?

# Load packages and data
library(tidyverse)
df = data.frame(n = c(2, 3, 5,10), 
                s = c("aa;bb;cc", "bb;dd;aa", "NA","xx;nn"),
                b = c("aa;bb;cc", "bb;dd;cc", "zz;bb;yy","NA"), 
                t = c("aa;bb;cc", "bb;dd", "kk", NA))

# Solution
dff <- df %>% 
  separate(col = "s", into = c("s1", "s2", "s3")) %>%
  separate(col = "b", into = c("b1", "b2", "b3")) %>%
  separate(col = "t", into = c("t1", "t2", "t3")) %>% # Solution here could be enhanced to take in n columns and put them into however many columns as needed, using map or apply. 
  rowid_to_column('id') %>% 
  gather(key, value, -(id:n)) %>% 
  mutate_at(vars(value), na_if, "NA") %>%
  drop_na(value) %>%
  group_by(id) %>%
  distinct(value, .keep_all = TRUE) %>%
  summarise(n = first(n), finalcol = paste(value, collapse = ';')) %>% 
  ungroup() %>% 
  select(-id)
#> Warning: Expected 3 pieces. Missing pieces filled with `NA` in 2 rows [3,
#> 4].
#> Warning: Expected 3 pieces. Missing pieces filled with `NA` in 1 rows [4].
#> Warning: Expected 3 pieces. Missing pieces filled with `NA` in 2 rows [2,
#> 3].
dff
#> # A tibble: 4 x 2
#>       n finalcol   
#>   <dbl> <chr>      
#> 1     2 aa;bb;cc   
#> 2     3 bb;dd;aa;cc
#> 3     5 zz;bb;yy;kk
#> 4    10 xx;nn

reprex package (v0.2.1) 于 2019 年 3 月 26 日创建

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-05
    • 2020-12-26
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多