【问题标题】:Conditioned based string matching using grepl and ifelse使用 grepl 和 ifelse 进行基于条件的字符串匹配
【发布时间】:2018-12-12 17:40:57
【问题描述】:

我有一个数据框 df,如下所述。

a <- c(1:6)
b <- c("Audi,BMW,Skoda, Rackets,Toy,Football",
       "Suzuki,Kawasaki,Ducati,Aprilia,Baseball, Rugby",
       "Mazda, Ford, chevrolet,Mercedes,Gloves,Helmet",
       "Lemon,Yamaha,Table,Kawasaki,Chair,Fruits", 
       "Ford, chevrolet,Bread,Ducati,Tesla,Hyundai",
       "Honey,Apple,Alcohol,cake,Sweets, Mango")
       df <- data.frame(a,b)

*

我还有两个包含汽车和自行车品牌名称的列表。

cars <- c("Audi","BMW","Ford","Skoda","Mazda","chevrolet","Mercedes","Volkswagen","Tesla","Hyundai","Lamborghini","Mini-Cooper","Lexus")
motorbike <- c("Yamaha","Suzuki","Kawasaki","Harley-Davidson","Ducati","Aprilia","KTM", "Triumph","Piaggio","Hyosung","Vespa","MV-Agusta")

我使用 grepl 和 ifelse 来匹配 df$b 中两个列表中的单词,如果匹配,则为每行分配一个值。

df$c<-ifelse(grepl(paste(cars, collapse="|"), df$b), "cars",
      ifelse(grepl(paste(motorbike, collapse="|"),df$b), "bikes","others"))

现在,我想设置一个条件,如果每行中有 4 个或超过 4 个单词匹配,则只有在 df$c 中分配一个值 (car,bike)。我希望我的 df 是这样的:

structure(list(a = 1:6, b = structure(c(1L, 6L, 5L, 4L, 2L, 3L
), .Label = c("Audi,BMW,Skoda, Rackets,Toy,Football", "Ford, chevrolet,Bread,Ducati,Tesla,Hyundai", 
"Honey,Apple,Alcohol,cake,Sweets, Mango", "Lemon,Yamaha,Table,Kawasaki,Chair,Fruits", 
"Mazda, Ford, chevrolet,Mercedes,Gloves,Helmet", "Suzuki,Kawasaki,Ducati,Aprilia,Baseball, Rugby"
), class = "factor"), c = c("others", "bikes", "cars", "others", 
"cars", "others")), row.names = c(NA, 6L), class = "data.frame") 

【问题讨论】:

    标签: r if-statement string-matching grepl


    【解决方案1】:

    这有帮助吗?当然,您可以删除 amountcars 和 amountmotors 列。您是否希望永远不会同时拥有> 3 辆汽车和> 3 台发动机?根据评论,我现在更新了我的答案。

    library(stringr)
    df$amountcars <- str_count(df$b, paste(cars, collapse="|"))
    df$amountmotors <- str_count(df$b, paste(motorbike, collapse="|"))
    
    
    
    df$c <- ifelse(df$amountcars > 3 & df$amountcars > df$amountmotors, "cars", ifelse(df$amountmotors > 3 & df$amountmotors > df$amountcars, "bikes", "others"))
    df
    
      a                                              b amountcars amountmotors      c
    1 1           Audi,BMW,Skoda, Rackets,Toy,Football          3            0 others
    2 2 Suzuki,Kawasaki,Ducati,Aprilia,Baseball, Rugby          0            4  bikes
    3 3  Mazda, Ford, chevrolet,Mercedes,Gloves,Helmet          4            0   cars
    4 4       Lemon,Yamaha,Table,Kawasaki,Chair,Fruits          0            2 others
    5 5     Ford, chevrolet,Bread,Ducati,Tesla,Hyundai          4            1   cars
    6 6         Honey,Apple,Alcohol,cake,Sweets, Mango          0            0 others
    

    如果您有 9 个字符串,则基于 cmets: 首先用字符串创建所有向量:

    cars <- c("Audi","BMW","Ford","Skoda","Mazda","chevrolet","Mercedes","Volkswagen","Tesla","Hyundai","Lamborghini","Mini-Cooper","Lexus")
    motorbike <- c("Yamaha","Suzuki","Kawasaki","Harley-Davidson","Ducati","Aprilia","KTM", "Triumph","Piaggio","Hyosung","Vespa","MV-Agusta")
    

    然后将它们放在一个列表中,并添加名称

    list1 <- list(cars, motorbike)
    names(list1) <- c("cars", "motorbike")
    

    最后,运行这段代码:

    df$d <- 
    ifelse(apply(sapply(list1, function(x) str_count(df$b, paste0(x, collapse = "|"))), 1, max) > 3,
    apply(sapply(list1, function(x) str_count(df$b, paste0(x, collapse = "|"))), 1, function(x) names(list1)[which.max(x)]),
    "others")
    

    基本上,它会根据其中一个向量计算最大字符串数,如果大于 3,则分配适当的名称,否则分配“其他”。

    【讨论】:

    • 您的方法部分正确。如果 df$b 有 20 个单词怎么办。 amountcars 有 7 个单词,amountmotors 有 13 个单词,在这种情况下,它会分配一个错误的值 'car'。我希望将 amountcars 和 amountmotors 之间计数值较大的行分配给 Car 或 Bike。
    • 这就是为什么我问你想在这种情况下发生什么,我现在更新了我的答案。 :)
    • 实际上我有 9 列要计数(str_count),然后我需要将值分配给其中最大的。很抱歉在之前的评论中没有提到这一点。是否有任何解决方案可以仅查看具有最大计数的列并将值分配给它?
    • 我想通了,我必须使用多个 & 条件。我有一个非常大的数据框,我认为这些运算符会增加运行时间。感谢您的帮助。
    • 我只是找到了一种不需要创建所有这些列的方法。让我更新我的答案
    猜你喜欢
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 2022-01-17
    相关资源
    最近更新 更多