【问题标题】:Splitting string column into many using tidyverse使用 tidyverse 将字符串列拆分为多个
【发布时间】:2019-06-07 07:26:12
【问题描述】:

我有一个带逗号的字符串列。我想将此单列转换为多个带标签的列,并正确填写值。输出数据框将有 3 列(A、B 和 C)。第 1 行的 A 列和 B 列用“是”填充,C 列用“否”填充。第 2 行将所有 3 列填充为“是”等。

df1 <- data.frame(X= c("A, B", "A, B, C", "A", "A, C"))

df1
        X
1    A, B
2 A, B, C
3       A
4    A, C

所需输出

A    B    C
Yes  Yes  No
Yes  Yes  Yes
Yes  No   No
Yes  No   Yes

任何提示,请。

【问题讨论】:

标签: r tidyverse tidyr comma stringr


【解决方案1】:

类似这样的:

library(tidyverse)

df1 %>%
  mutate(id = row_number()) %>% 
  separate_rows(X) %>% 
  group_by(id) %>% 
  mutate(Y = "yes") %>% 
  spread(X, Y, fill = "no")

# A tibble: 4 x 4
# Groups:   id [4]
     id A     B     C    
  <int> <chr> <chr> <chr>
1     1 yes   yes   no   
2     2 yes   yes   yes  
3     3 yes   no    no   
4     4 yes   no    yes  

【讨论】:

    【解决方案2】:

    这是一个使用base R 和table 的选项。我们将“X”列按, 拆分为vectors 的list,用stack 将其转换为两列data.frame,用table 获取频率并将其转换为逻辑

    table(stack(setNames(strsplit(as.character(df1$X), ", +"), 
                        seq_len(nrow(df1))))[2:1]) > 0
     #   values
    #ind    A     B     C
    #  1 TRUE  TRUE FALSE
    #  2 TRUE  TRUE  TRUE
    #  3 TRUE FALSE FALSE
    #  4 TRUE FALSE  TRUE
    

    【讨论】:

      【解决方案3】:

      通过stringi

      stringi::stri_split_fixed(df1$X, ", ", simplify = TRUE) != ""
      #      [,1]  [,2]  [,3]
      # [1,] TRUE  TRUE FALSE
      # [2,] TRUE  TRUE  TRUE
      # [3,] TRUE FALSE FALSE
      # [4,] TRUE  TRUE FALSE
      

      TRUE/FALSE 本质上是yes/no,但如果您需要字符矩阵,您可以随时使用ifelse(., "yes", "no") 并保留矩阵结构。

      【讨论】:

        【解决方案4】:

        一种稍微不同的方法,不依赖于分组。最终转换为“是/否”也是按列执行的,而不是依赖于从长数据到宽数据的转换。对于非常大的数据集,这可能会更有效。

        df2 <- df1 %>% 
          mutate(row_num = 1:n()) %>% 
          separate_rows(X) %>% 
          spread(X, 1) %>% 
          select(-row_num) %>% 
          mutate_all(~ifelse(!is.na(.), 'Yes', 'No'))
        
            A   B   C
        1 Yes Yes  No
        2 Yes Yes Yes
        3 Yes  No  No
        4 Yes  No Yes
        

        【讨论】:

          【解决方案5】:

          使用splitstackshape

          library(splitstackshape)
          newdf=cSplit_e(df1, "X", sep = ", ",type = "character")
          newdf[newdf==1]='Yes'
          newdf[is.na(newdf)]='No'
          
          newdf
                  X X_A X_B X_C
          1    A, B Yes Yes  No
          2 A, B, C Yes Yes Yes
          3       A Yes  No  No
          4    A, C Yes  No Yes
          

          【讨论】:

            【解决方案6】:

            这是base中的另一个解决方案

            lets <- strsplit(as.character(.subset2(df1,1L)), ', ')
            lets_unique <- unique(unlist(lets))
            vapply(seq_along(lets_unique),function(k)grepl(lets_unique[k],lets),logical(length(lets)))
            #      [,1]  [,2]  [,3]
            # [1,] TRUE  TRUE FALSE
            # [2,] TRUE  TRUE  TRUE
            # [3,] TRUE FALSE FALSE
            # [4,] TRUE FALSE  TRUE
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-08-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-04-04
              • 1970-01-01
              • 2022-11-23
              相关资源
              最近更新 更多