【问题标题】:If elements are different, collapse如果元素不同,则折叠
【发布时间】:2021-01-25 11:28:50
【问题描述】:

如果两列不同,我想折叠它们。如果它们相同,则保留该值。如果有一个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

【问题讨论】:

    标签: r database dataframe collapse


    【解决方案1】:

    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  
    

    【讨论】:

    • 好鸭,又简洁又快速。
    • 鸭子,我可以看到没有空格参数,第一行的 A 后面有一个逗号。它用空格替换 ',' 然后 trimws 删除它?
    【解决方案2】:

    这行得通吗:

    > 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
    > 
    

    【讨论】:

      【解决方案3】:

      这是另一个tidyverse 选项。

      如果您想摆脱烦人的空字符串"" 并使其成为NA,您可以使用na_if

      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
      

      【讨论】:

        【解决方案4】:

        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" 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-07
          • 2020-09-15
          • 2012-09-24
          • 1970-01-01
          • 1970-01-01
          • 2022-01-19
          • 2015-02-09
          • 2013-10-10
          相关资源
          最近更新 更多