【问题标题】:Reducing nested if else statements with grepl in R在 R 中使用 grepl 减少嵌套的 if else 语句
【发布时间】:2021-11-09 13:45:27
【问题描述】:

在 R 中,我有一个数据框,其中有一列“食物”,其中包含 100 多个不同的字符串值。

例如:

id<-c("1", "2", "3", "4", "5", "6")
food <- c("X1_", "X2_", "X3_", "X4_", "X5_", "X100_")
df <- data.frame(id, food)

我想根据“food”列中的字符串创建一个新列“food_final”。我开始使用嵌套的 ifelses 和 grepl 编写代码,但是考虑到有 100 多个不同的字符串值,我知道拥有 100 多个 if else 绝对是不是这样做的最干净的方式,无论如何,一个人可以拥有多少个。

到目前为止我尝试过的示例:

df$food_final<-ifelse(grepl("X1_", df$food, ignore.case=TRUE), "1",
                      ifelse(grepl("X2_", df$food, ignore.case=TRUE), "2",
                             ifelse(grepl("X3_", df$food, ignore.case=TRUE), "3",
                                    ifelse(grepl("X4_", df$food, ignore.case=TRUE), "4",
                                        ifelse(grepl("X5_", df$food, ignore.case=TRUE), "5",
                                             ifelse(grepl("X100_", df$food, ignore.case=TRUE), "100", NA))))))

创建这个新列“food_final”的最佳方法是什么,而不是使用这么多嵌套的 ifelse 语句?

提前谢谢你。

【问题讨论】:

    标签: r if-statement nested grepl


    【解决方案1】:

    您也许可以在sub 的帮助下使用单行解决方案:

    df$food_final <- sub("^X(\\d+)_$", "\\1", df$food)
    

    【讨论】:

    • 谢谢 - 干净多了!
    【解决方案2】:

    如果您只是想从readr 中提取我喜欢使用parse_number 的字符串中的数字。

    df$food_final<-parse_number(df$food)
    

    【讨论】:

    • 谢谢 - 我不知道 parse_number,所以这真的很有用。
    【解决方案3】:

    如果你想提取数字:

    df$food_final <- gsub("\\D", "", df$food)
    
    df
    #  id  food food_final
    #1  1   X1_          1
    #2  2   X2_          2
    #3  3   X3_          3
    #4  4   X4_          4
    #5  5   X5_          5
    #6  6 X100_        100
    

    或者,如果存在不同的链接,则与嵌套的 ifelse 基本相同。

    x <- c("1"="X1_", "2"="X2_", "3"="X3_", "4"="X4_", "5"="X5_", "100"="X100_")
    apply(sapply(x, grepl, df$food, ignore.case=TRUE), 1, function(y) names(x)[y][1])
    #[1] "1"   "2"   "3"   "4"   "5"   "100"
    

    或者使用Reduce:

    x <- c("1"="X1_", "2"="X2_", "3"="X3_", "4"="X4_", "5"="X5_", "100"="X100_")
    Reduce(function(a,b) {
      i <- is.na(a)
      a[i][grepl(x[b], df$food[i], ignore.case=TRUE)] <- b
      a
    }, names(x), rep(NA, nrow(df)))
    #[1] "1"   "2"   "3"   "4"   "5"   "100"
    

    【讨论】:

    • 谢谢 - 我很欣赏包含替代品。这几乎就像你预料到一个潜在的后续问题;-)
    【解决方案4】:

    您也可以使用str_extract 仅提取数字:

    library(stringr)
    df$food_final <- str_extract(df$food, "\\d+")
    

    【讨论】:

      【解决方案5】:

      我们可以使用来自tidyr 包的extract_numeric

      library(dplyr)
      library(tidyr)
      
      df %>% 
        mutate(final_food = extract_numeric(food))
      

      输出:

        id  food final_food
      1  1   X1_          1
      2  2   X2_          2
      3  3   X3_          3
      4  4   X4_          4
      5  5   X5_          5
      6  6 X100_        100
      

      【讨论】:

      • 您好,extract_numeric 现在已弃用,取而代之的是 parse_number。请参阅上面的解决方案
      • 谢谢。我通常使用parse_number,但不知何故忘记了extract_numeric已被弃用!
      猜你喜欢
      • 1970-01-01
      • 2020-06-17
      • 2021-01-10
      • 2020-09-06
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      相关资源
      最近更新 更多