【问题标题】:R switch statement on comparisons关于比较的 R switch 语句
【发布时间】:2012-09-04 22:32:41
【问题描述】:

我正在尝试编写一个 R 脚本来根据在范围内拟合值来评估不同的表达式。这个想法是,如果 Length 在一个范围内,它将以一种方式进行评估,如果它在一个较长的范围内,它将以不同的方式进行评估。

我可以使用 if/else 语句来完成这项工作,但它非常难看,而且我相信一定有更好的方法......这是有效的代码。

Length=8.2

if (Length<1) 
    mode="Walk"
else if (1<=Length & Length <5)
    mode="bike" 
else if (5<=Length & Length <10)
    mode="drive"
else if (Length>=10)
    mode="fly"

我一直在尝试用 switch 函数做一些事情,但它似乎只适用于文本或整数......有没有办法让 switch 语句在每种情况下进行评估,比如这样?

Length=3.5

switch(Length,
       (Length<1)  mode="Walk"
       (1<=Length & Length <5)  mode="bike"
       (5<=Length & Length <10)  mode="drive"
       (Length=>10)  mode="fly"
)

【问题讨论】:

  • 不知道是否有帮助,但我建议对您的“丑陋”代码进行编辑,使其不那么丑陋。
  • 这里给出了使用switch()match() 的解决方案(2014 年晚些时候):stackoverflow.com/a/27279612/1103558

标签: r if-statement switch-statement


【解决方案1】:

这是与 Josh 类似的答案,但使用的是 findInterval

Length <- 0:11

cuts <- c(-Inf, 1, 5, 10, Inf)
labs <- c("Walk", "bike", "drive", "fly")

labs[findInterval(Length, cuts)]
# [1] "Walk"  "bike"  "bike"  "bike"  "bike"  "drive" "drive"
# [8] "drive" "drive" "drive" "fly"   "fly"

您也可以使用嵌套的ifelse 语句,这是一个口味问题:

ifelse(Length < 1,  "Walk",
ifelse(Length < 5,  "bike",
ifelse(Length < 10, "drive",
                    "fly")))
# [1] "Walk"  "bike"  "bike"  "bike"  "bike"  "drive" "drive"
# [8] "drive" "drive" "drive" "fly"   "fly"

【讨论】:

  • 好的,可以,谢谢!而且它看起来确实比我的烂摊子更具可读性。
【解决方案2】:

使用 dplyr 的case_when 声明:

library(dplyr)
Length <- 3.5
mode <- case_when(
                Length < 1 ~ "Walk",
                1 <= Length & Length < 5 ~ "bike",
                5 <= Length & Length < 10 ~ "drive",
                Length >= 10 ~ "fly"
          )
mode
#> [1] "bike"

【讨论】:

    【解决方案3】:

    cut() 会做你需要的吗?

    Length <- 0:11
    
    cuts <- c(-Inf, 1, 5, 10, Inf)
    labs <- c("Walk", "bike", "drive", "fly")
    
    as.character(cut(Length, breaks = cuts, labels = labs, include.lowest=TRUE))
    #  [1] "Walk"  "Walk"  "bike"  "bike"  "bike"  "bike"  "drive" "drive" "drive"
    # [10] "drive" "drive" "fly"  
    

    【讨论】:

    • 这对于我发布的简化示例很有用,但对于我真正想做的事情可能不太好......我需要每个案例来评估一个单独的方程,而不是仅仅选择一个标签.
    • @mooseo -- 但是现在你有了一个字符向量,你可以将它提供给switch()...
    【解决方案4】:

    Cut and Switch:使用 cut() 中的因子级别并传递到 switch() 以返回适当的代码。

     transport <- function(dist) {
       stopifnot(is.numeric(dist))
       x <- as.numeric(cut(dist, c(-Inf,0,1,5,10,Inf)), right = TRUE)
       switch (x,
               "No distance",
               "Walk",
               "Bike",
               "Drive",
               "Fly",
               stop("Not sure")
       )
     }
    

    【讨论】:

      【解决方案5】:

      这个答案对于手头的例子来说有点过头了,但它非常灵活——你可以在evaluate_like_this() 中做任何事情。

      evaluate_one <- function(x) {
        switch(
          x,
          evaluate_like_this(x, "Walk"),
          evaluate_like_this(x, "No distance"),
          evaluate_like_this(x, "Bike"),
          evaluate_like_this(x, "Drive"),
          evaluate_like_this(x, "Fly")
        )
      }
      
      evaluate_like_this <- function(x, y) {
        paste0(x, ": ", y)
      }
      
      these_data <- 0:11
      intervals <- cut(these_data, breaks = c(-Inf, 1, 5, 10, Inf), label = FALSE)
      unlist(lapply(intervals, evaluate_one))
      #>  [1] "1: Walk"        "1: Walk"        "2: No distance" "2: No distance"
      #>  [5] "2: No distance" "2: No distance" "3: Bike"        "3: Bike"       
      #>  [9] "3: Bike"        "3: Bike"        "3: Bike"        "4: Drive"
      

      reprex package (v0.2.1) 于 2018 年 12 月 19 日创建

      【讨论】:

        【解决方案6】:
        length <- 3.5
        cuts <- c( 1, 5, 10, Inf )
        labs <- c( "Walk", "bike", "drive", "fly" )
        x <- which( cuts > length )[1]
        switch(x,{labs[1]},{labs[2]},{labs[3]},{labs[4]})
        

        【讨论】:

        • 这个答案被标记为Low Quality 并且可以从解释中受益。以下是How do I write a good answer? 的一些指南。仅代码答案不被视为好的答案,并且可能会被否决和/或删除,因为它们对学习者社区不太有用。它只对你很明显。解释它的作用,以及它与现有答案的不同/更好From Review
        猜你喜欢
        • 1970-01-01
        • 2015-12-11
        • 2016-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-30
        相关资源
        最近更新 更多