【问题标题】:Split string over list of words在单词列表上拆分字符串
【发布时间】:2018-06-15 23:02:09
【问题描述】:

我有一个来自二手来源的数据框,其中一列中有很多关键信息,用空格分隔。我不能简单地使用str_split,因为某些关键信息的名称中有空格,但它们前面有一个分组变量。以下是使用食物和食物组的示例:

foo1 <- paste('FRUIT', 'Apple', 'PROTEIN', 'Chicken', 'STARCH', 'Banana Bread', 'FRUIT', 'Strawberry')
foo2 <- paste('PROTEIN', 'Pork', 'FAT', 'Butter', 'FRUIT', 'Banana', 'STARCH', 'Spaghetti')
foo3 <- paste('FRUIT', 'Strawberry', 'PROTEIN', 'Lean Steak', 'FRUIT', 'Strawberry', 'STARCH', 'Potato')

df <- rbind(foo1, foo2, foo3)
df

foo1 "FRUIT Apple PROTEIN Chicken STARCH Banana Bread FRUIT Strawberry"  
foo2 "PROTEIN Pork FAT Butter FRUIT Banana STARCH Spaghetti"             
foo3 "FRUIT Strawberry PROTEIN Lean Steak FRUIT Strawberry Starch Potato"

在这种情况下,我想要获取的关键部分是实际的食物,但我不能分割空间,因为存在诸如“香蕉面包”之类的东西。因此,我只能拆分 FRUIT、PROTEIN、STARCH 或 FAT,但我想不出一个好的方法来做到这一点。在我的实际表中,仍然只有 4 个“分组”,但有 500 多个单独的项目,因此尝试用空格映射特定的项目将是一个巨大的痛苦。以下行不起作用:

str_split(df, c('FRUIT', 'PROTEIN', 'STARCH', 'FAT'))
str_split_fixed(df, c('FRUIT', 'PROTEIN', 'STARCH', 'FAT'), 4)

有什么想法吗?提前致谢。

【问题讨论】:

    标签: r regex string split


    【解决方案1】:

    您可以使用正则表达式来做到这一点:

    str_split(df, c('FRUIT|PROTEIN|STARCH|FAT'))
    [[1]]
    [1] ""               " Apple "        " Chicken "      " Banana Bread " " Strawberry"   
    
    [[2]]
    [1] ""           " Pork "     " Butter "   " Banana "   " Spaghetti"
    
    [[3]]
    [1] ""             " Strawberry " " Lean Steak " " Strawberry " " Potato"    
    

    使用 paste 中的折叠 arg 将您的 vec 转换为正则表达式:

    paste(c('FRUIT', 'PROTEIN', 'STARCH', 'FAT'), collapse = '|')
    [1] "FRUIT|PROTEIN|STARCH|FAT"
    

    最好的,

    科林

    【讨论】:

      【解决方案2】:

      由于您只想要食物,因此使用tidyverse 的以下方法应该可以解决问题:

      library(stringr)
      library(tidyverse)
      
      foo1 <- paste('FRUIT', 'Apple', 'PROTEIN', 'Chicken', 'STARCH', 'Banana Bread', 'FRUIT', 'Strawberry')
      foo2 <- paste('PROTEIN', 'Pork', 'FAT', 'Butter', 'FRUIT', 'Banana', 'STARCH', 'Spaghetti')
      foo3 <- paste('FRUIT', 'Strawberry', 'PROTEIN', 'Lean Steak', 'FRUIT', 'Strawberry', 'STARCH', 'Potato')
      
      df <- rbind(foo1, foo2, foo3) %>%
        as_tibble()
      

      (注意使用 as_tibble() 将数据框转换为 tibble 对象 - 更易于使用)

      现在是实际的东西:

      df.new <- df %>% 
         mutate(clean.str = str_replace_all(V1, pattern = "(FRUIT|PROTEIN|STARCH|FAT)", replacement = "|") %>%
             str_sub(start = 3)) %>%
         mutate(str.ls = str_split(clean.str, fixed(" | "))) %>%
         unnest() %>% 
         select(str.ls)
      

      这是你想要的结果,一份实际食物的清单:

      df.new
      
      # A tibble: 12 x 1
           str.ls
            <chr>
        1        Apple
        2      Chicken
        3 Banana Bread
        4   Strawberry
        5         Pork
        6       Butter
        7       Banana
        8    Spaghetti
        9   Strawberry
       10   Lean Steak
       11   Strawberry
       12       Potato
      

      【讨论】:

        【解决方案3】:

        我会这样做。这看起来很简短,很容易理解。

        df%>%
        strsplit(split = paste(c('FRUIT', 'PROTEIN', 'STARCH', 'FAT'), collapse = "|"))%>%
        unlist()%>%
        .[. != ""]
        
         [1] " Apple "        " Chicken "      " Banana Bread " " Strawberry"    " Pork "         " Butter "       " Banana "       " Spaghetti"    
         [9] " Strawberry "   " Lean Steak "   " Strawberry "   " Potato" 
        

        【讨论】:

          【解决方案4】:

          unnest_tokens() 中使用stri_split_regex(),我们可以提供以下结果。 unnest_tokens()tidytext 包中的一个函数。在这里,我使用stri_split_regex() 作为unnest_tokens() 中的自定义函数。正则表达式说,“以行开头或空格开头的模式和重复的大写字母(一次或多次)跟随,并且模式以空格结尾”。这使我们可以按照您在问题中的描述拆分字符串。行名帮助我们查看哪些单词在哪些字符串中。

          library(tidytext)
          library(stringi)
          
          df <- data.frame(text = c(foo1, foo2, foo3), stringsAsFactors = FALSE)
          
          df %>%
          unnest_tokens(input = text, output = word, to_lower = FALSE,
                        token = stri_split_regex, 
                        pattern = "(\\s|^)[A-Z]+\\s", omit_empty = TRUE)
          
                      word
          1          Apple
          1.1      Chicken
          1.2 Banana Bread
          1.3   Strawberry
          2           Pork
          2.1       Butter
          2.2       Banana
          2.3    Spaghetti
          3     Strawberry
          3.1   Lean Steak
          3.2   Strawberry
          3.3       Potato
          

          【讨论】:

            【解决方案5】:

            使用使用 do.callstrsplit 的 Base R,您可以根据当前设置拆分和合并结果,您可以尝试:

            do.call("rbind", strsplit(df[,1], "FRUIT|PROTEIN|STARCH|FRUIT|FAT", perl=T))[,2:5]
            

            输出

              #         [,1]           [,2]           [,3]             [,4]         
              #  foo1 " Apple "      " Chicken "    " Banana Bread " " Strawberry"
              #  foo2 " Pork "       " Butter "     " Banana "       " Spaghetti" 
              #  foo3 " Strawberry " " Lean Steak " " Strawberry "   " Potato"  
            

            【讨论】:

              【解决方案6】:

              首先注意问题中的df是矩阵,不是数据框:

              class(df)
              ## [1] "matrix"
              

              我们可以使用strsplit 使用正则表达式pat 分割大写单词和周围的空格。请注意,"\\b" 匹配单词边界。 Filter(nzchar, ...) 删除零长度字符串,unique 删除重复项。没有使用任何包。

              pat <- " *\\b([A-Z]+)\\b *" 
              unique(Filter(nzchar, unlist(strsplit(df[, 1], pat))))
              

              给予:

              [1] "Apple"        "Chicken"      "Banana Bread" "Strawberry"   "Pork"        
              [6] "Butter"       "Banana"       "Spaghetti"    "Lean Steak"   "Potato" 
              

              也可以使用这样的 magrittr 管道编写:

              library(magrittr)
              
              df[, 1] %>%
                      strsplit(pat) %>%
                      unlist %>%
                      Filter(nzchar, .) %>%
                      unique
              

              【讨论】:

                猜你喜欢
                • 2021-05-26
                • 2017-08-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-01-22
                • 1970-01-01
                • 2018-04-06
                • 2011-11-03
                相关资源
                最近更新 更多