代码之家  ›  专栏  ›  技术社区  ›  MYaseen208

使用tidyverse将字符串列拆分为多个

  •  2
  • MYaseen208  · 技术社区  · 6 年前

    我有一个带逗号的字符串列。我想将这个单列转换为多个带标签的列,并适当地填充值。输出数据帧将有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
    

    有什么提示吗?

    6 回复  |  直到 6 年前
        1
  •  4
  •   phiver    6 年前

    像这样:

    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
  •  3
  •   akrun    6 年前

    这里有一个使用 base R 具有 table . 我们将“x”列拆分为 , 变成一个 list 属于 vector s,将其转换为两列 data.frame 具有 stack ,获取频率 桌子 并将其转换为逻辑

    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
  •  3
  •   Rich Scriven    6 年前

    通孔 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
  •  2
  •   jdobres    6 年前

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

    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
  •  2
  •   niko    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
    
        6
  •  1
  •   BENY    6 年前

    使用 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
    
    推荐文章