【问题标题】:How can I group a column based off of a list of string patterns in R?如何根据 R 中的字符串模式列表对列进行分组?
【发布时间】:2020-10-05 09:09:05
【问题描述】:

我有一个数据框,其中有一列字符串,如下所示:

String_Column      Rating
Greenyy             1
BigGREENglow        2
BLUEBERRY           8
Shiny Emeralds      3
Sky Blue            3
Skyblue             6 
CERULEAN            2
Blueish Green       5
BLOO                3

我想为这些值创建分组,所以如果它有一个与绿色同义的词或包含绿色这个词的任何变体,我想将它分组为“绿色”。蓝色也一样。

所以我希望上面看起来像这样:

String_Column     Grouping      Rating
Greenyy           Green         1
BigGREENglow      Green         2 
BLUEBERRY         Blue          8
Shiny Emeralds    Green         3
Sky Blue          Blue          3
Skyblue           Blue          6
CERULEAN          Blue          2
Blueish Green     Green         5  
BLOO              Not Found     3

我创建了一个蓝色列表和一个绿色列表,其中包含与每个相关的单词。

Blue_List <- c("Blue", "BLUE", "blue", "Cerulean" , "CERULEAN", "cerulean" , "Sapphire", "sapphire" , "SAPPHIRE")

Green_List <- c("Green", "GREEN", "green", "Chartreuse", "CHARTREUSE", "chartreuse", "Emerald", "emerald", "EMERALD")

然后我想根据每个字符串是否在此列表中将其分组为蓝色或绿色。 并将此列添加到数据框中。如果该值不包含在列表中,则返回“未找到”

我已经能够做到这一点,

    DF$Grouping<-ifelse(grepl("TRUE",sapply(DF$String_Column, grepl, Green_List,ignore.case=TRUE, simplify=FALSE)),  "Green" ,
    grepl("TRUE",sapply(DF$String_Column, grepl, Blue_List,ignore.case=TRUE, simplify=FALSE)),"Blue" ,"Not Found")

但是,我需要保留分组的顺序,我不知道该怎么做。 对于“蓝绿色”的示例,我希望将其归类为绿色,但在读取 else 子句时将其放入蓝色分组中。

我想我可以将 ifelse 重新排序为首先具有“蓝色”,但实际数据集比我共享的要复杂一些,并且我最终希望对数据集的子集执行每个“else” '不是事先分组。

任何帮助将不胜感激!谢谢!

【问题讨论】:

    标签: r list if-statement sapply grepl


    【解决方案1】:

    这是一个基本的 R 方法。我将减少列表,因为我们可以使用ignore.case=TRUE,但这不是严格要求:如果大小写很重要,则删除该组件。我唯一真正依赖的是每个元素的第一个元素都是相关的(并且会从中收集到名称)。

    tmpstr <- Reduce(function(s, lst) gsub(paste0("(", paste(lst, collapse = "|"), ")"), lst[1], s, ignore.case = TRUE),
                     list(Blue_List, Green_List), init = dat$String_Column)
    tmpcolors <- regmatches(tmpstr,
                            gregexpr(paste0("(", paste(Blue_List[1], Green_List[1], sep = "|"), ")"),
                                     tmpstr, ignore.case = TRUE))
    tmpcolors <- replace(tmpcolors, sapply(tmpcolors, Negate(length)), NA_character_)
    tmpcolors <- sapply(tmpcolors, tail, n = 1)
    tmpcolors[ is.na(tmpcolors) ] <- "Not Found"
    dat$Grouping <- tmpcolors
    dat
    #      String_Column Rating  Grouping
    # 1 Greenyy               1     Green
    # 2 BigGREENglow          2     Green
    # 3 BLUEBERRY             8      Blue
    # 4 Shiny Emeralds        3     Green
    # 5 Sky Blue              3      Blue
    # 6 Skyblue               6      Blue
    # 7 CERULEAN              2      Blue
    # 8 Blueish Green         5     Green
    # 9 BLOO                  3 Not Found
    

    事实上,如果你有两个以上的颜色列表,你可以简单地提供一个任意颜色集合的列表:

    Color_Lists <- list(
      c("Blue", "cerulean" , "sapphire"),
      c("Green", "chartreuse", "emerald")
    )
    tmpstr <- Reduce(function(s, lst) gsub(paste0("(", paste(lst, collapse = "|"), ")"), lst[1], s, ignore.case = TRUE),
                     Color_Lists, init = dat$String_Column)
    tmpcolors <- regmatches(tmpstr,
                            gregexpr(paste0("(", paste0(sapply(Color_Lists, `[[`, 1), collapse = "|"), ")"),
                                     tmpstr, ignore.case = TRUE))
    tmpcolors <- replace(tmpcolors, sapply(tmpcolors, Negate(length)), NA_character_)
    tmpcolors <- sapply(tmpcolors, tail, n = 1)
    tmpcolors[ is.na(tmpcolors) ] <- "Not Found"
    dat$Grouping <- tmpcolors
    

    数据:

    从“蓝绿色”得到“绿色”的假设是它是最后引用的颜色。如果您的规则比“最后提到的”更复杂,那么……也许这不会完美。

    dat <- read.table(header=TRUE, sep="|", text="
    String_Column   |   Rating
    Greenyy         |    1
    BigGREENglow    |    2
    BLUEBERRY       |    8
    Shiny Emeralds  |    3
    Sky Blue        |    3
    Skyblue         |    6 
    CERULEAN        |    2
    Blueish Green   |    5
    BLOO            |    3")
    
    Blue_List <- c("Blue", "cerulean" , "sapphire")
    Green_List <- c("Green", "chartreuse", "emerald")
    

    【讨论】:

      【解决方案2】:

      希望你能用这个

      #data
      string_Column <- c("Greenyy","BigGREENglow","BLUEBERRY","Shiny Emeralds","Sky Blue","Skyblue","CERULEAN","Blueish Green","BLOO")
      Rating <- c(1,2,8,3,3,6,2,5,3)
      df <- as.data.frame(cbind(string_Column,Rating))
      
      #green and blue vector
      Blue_List <- c("Blue", "BLUE", "blue", "Cerulean" , "CERULEAN", "cerulean" , "Sapphire", "sapphire" , "SAPPHIRE")
      Green_List <- c("Green", "GREEN", "green", "Chartreuse", "CHARTREUSE", "chartreuse", "Emerald", "emerald", "EMERALD")
      
      
      #applied function
      test <- function(x) {
        if(grepl(paste(Green_List,collapse = "|"), x[1])){
          return("Green")
        }
        if(grepl(paste(Blue_List,collapse = "|"), x[1])){
          return("Blue")
        }
        return("none")
      }
      
      #save the new vector to dataframe
      df$group <- unlist(apply(df, MARGIN = 1, test))
      

      输出:

      string_Column  Rating   group
      1   Greenyy         1   Green
      2   BigGREENglow    2   Green
      3   BLUEBERRY       8   Blue
      4   Shiny Emeralds  3   Green
      5   Sky Blue        3   Blue
      6   Skyblue         6   Blue
      7   CERULEAN        2   Blue
      8   Blueish Green   5   Green
      9   BLOO            3   none
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-26
        • 2015-01-11
        • 1970-01-01
        • 1970-01-01
        • 2021-12-20
        • 2021-12-22
        • 1970-01-01
        相关资源
        最近更新 更多