如果元素不同,则折叠

If elements are different, collapse

我有两列,如果它们不同,我想折叠它们。如果它们相同,则保留该值。如果有一个NA,保留另一个

df
#   element1 element2
#1        A         
#2        B        B
#3        C        D
#4        A     <NA>

我需要以下列:

#  element1 element2 element12
#1        A                  A
#2        B        B         B
#3        C        D       C,D
#4        A     <NA>         A

关于我该怎么做的任何提示?

数据:

df = data.frame(element1 = c("A", "B",  "C","A"),
                 element2 = c("", "B","D", NA));df

apply() 试试这个方法:

#Code 1
df$Var <- apply(df[1:2],1,function(x) trimws(paste0(unique(x[!is.na(x)]),collapse = ','),
                                             whitespace = ','))

输出:

  element1 element2 Var
1        A            A
2        B        B   B
3        C        D C,D
4        A     <NA>   A

dplyr 版本:

library(dplyr)
#Code
df %>% mutate(across(everything(),~as.character(.))) %>%
  replace(is.na(.),',') %>%
  rowwise() %>%
  mutate(Var=trimws(paste0(unique(c_across(element1:element2)),
                                              collapse = ','),whitespace = ',')) %>%
  replace(.==',',NA)

输出:

# A tibble: 4 x 3
# Rowwise: 
  element1 element2 Var  
  <chr>    <chr>    <chr>
1 A        ""       A    
2 B        "B"      B    
3 C        "D"      C,D  
4 A         NA      A  

这个有用吗:

> df %>% mutate(element3 = case_when(
There were 14 warnings (use warnings() to see them)
+                                   element1 == element2 ~ element1,
+                                   is.na(element1) & !is.na(element2) ~ element2,
+                                   is.na(element2) & !is.na(element1) ~ element1,
+                                   element1 == '' & element2 != '' ~ element2,
+                                   element1 != '' & element2 == '' ~ element1,
+                                   element1 != element2 ~ paste(element1, element2, sep = ',')
+ ))
  element1 element2 element3
1        A                 A
2        B        B        B
3        C        D      C,D
4        A     <NA>        A
> 

这是另一个 tidyverse 选项。

如果你想摆脱烦人的空字符串 "" 并使它们成为 NA,你可以使用 na_if.

A case_when 可以连接不同的字符串,使用 coalesce 以防一个或另一个丢失 (NA)。

如果两者都不是,则两列相同,只需设置为第一个值即可。

library(tidyverse)

df %>%
  na_if("") %>%
  mutate(element12 = case_when(
    element1 != element2 ~ paste(element1, element2, sep = ','),
    is.na(element1) | is.na(element2) ~ coalesce(element1, element2),
    TRUE ~ element1))

输出

  element1 element2 element12
1        A     <NA>         A
2        B        B         B
3        C        D       C,D
4        A     <NA>         A

base R中,我们可以用pastesub

来做到这一点
df$elements12 <- gsub("(?<=.)(?=.)", ",", sub("(.)\1+", "\1", 
     do.call(paste, c(replace(df, is.na(df), ""), sep=""))), perl = TRUE)

-输出

df$element12
#[1] "A"   "B"   "C,D" "A"