【问题标题】:Nested if statements - R嵌套 if 语句 - R
【发布时间】:2016-10-11 13:25:20
【问题描述】:

我遇到了多个 if 语句的问题。输出总是取自第一个条件,即使条件不正确。谁能指出我做错了什么?

代码:

for(i in 1:length(data_model3$Gewicht)){
    if (data_model3$Gewicht[i] < 1){
      data_model3$LIXshipping <- 3.26 
    }
    else if (data_model3$Gewicht[i] > 1 & data_model3$Gewicht[i] < 2){
      data_model3$LIXshipping <- 3.26 
    }
    else if (data_model3$Gewicht[i] > 2 & data_model3$Gewicht[i] < 3){
      data_model3$LIXshipping <- 3.86 
    }
    else if (data_model3$Gewicht[i] > 3 & data_model3$Gewicht[i] < 4){
      data_model3$LIXshipping <- 3.86 
    }
    else if (data_model3$Gewicht[i] > 4 & data_model3$Gewicht[i] < 5){
      data_model3$LIXshipping <- 3.86 
    }
    else if (data_model3$Gewicht[i] > 5 & data_model3$Gewicht[i] < 10){
      data_model3$LIXshipping <- 4.39 
    }
    else if (data_model3$Gewicht[i] > 10 & data_model3$Gewicht[i] < 20){
      data_model3$LIXshipping <- 4.81 
    }
    else if (data_model3$Gewicht[i] > 20 & data_model3$Gewicht[i] < 31.5){
      data_model3$LIXshipping <- 6.34 
    }
    else 
      data_model3$LIXshipping <- 17.09 
}

输出:

count_code  Gewicht LIXshipping
281         4.67    3.26
683         3.34    3.26
903         14.56   3.26
7390        14.62   3.26
2778        2.86    3.26
2778        10.37   3.26

对于你们中的一些人来说,这可能是一个完全基本的问题,但我不知道如何解决它。

【问题讨论】:

  • 使用cut 而不是嵌套的if/else。此外,您可以使用矢量化的ifelse
  • data_model3$LIXshipping &lt;- ... 正在更改整个列。
  • 请将dput(data_model3) 的结果放入您的问题中。

标签: r if-statement


【解决方案1】:

这可以通过一行来完成(+ 一行数据):

data_model3 <- data.frame(Gewicht=1:40)
data_model3$LIXshipping <- as.numeric(as.character(cut(data_model3$Gewicht, breaks=c(0,2,5,10,20,31.5, 100), labels=c(3.26, 3.86, 4.39, 4.81, 6.34, 17.09), right=FALSE)))

【讨论】:

    【解决方案2】:

    我会把规则放在一个表格中......

    library(data.table)
    setDT(df)
    
    rules = data.table(
      Gewicht = c(1:5, 10, 20, 31.5, Inf), 
      v = c(3.26, 3.26, 3.86, 3.86, 3.86, 4.39, 4.81, 6.34, 17.09)
    )
    
    
       Gewicht     v
    1:     1.0  3.26
    2:     2.0  3.26
    3:     3.0  3.86
    4:     4.0  3.86
    5:     5.0  3.86
    6:    10.0  4.39
    7:    20.0  4.81
    8:    31.5  6.34
    9:     Inf 17.09
    

    然后使用“滚动连接”来应用它们

    DF[, v := rules[DF, on="Gewicht", roll=-Inf, v] ]
    
    
        Gewicht     v
     1:       0  3.26
     2:       2  3.26
     3:       4  3.86
     4:       6  4.39
     5:       8  4.39
     6:      10  4.39
     7:      12  4.81
     8:      14  4.81
     9:      16  4.81
    10:      18  4.81
    11:      20  4.81
    12:      22  6.34
    13:      24  6.34
    14:      26  6.34
    15:      28  6.34
    16:      30  6.34
    17:      32 17.09
    18:      34 17.09
    19:      36 17.09
    20:      38 17.09
    21:      40 17.09
        Gewicht     v
    

    数据:

    DF = data.frame(Gewicht = seq(0,40,by=2))
    

    【讨论】:

      【解决方案3】:

      这不是直接回答问题,但我想展示带有矢量化 ifelse 的代码的样子,正如 @akrun 和 @Tim 所建议的那样,加上我的一些优化:

      data_model3 <- data.frame(Gewicht=1:40)
      
      data_model3$LIXshipping <- 
          ifelse (data_model3$Gewicht < 2,  3.26,
          ifelse (data_model3$Gewicht < 5,  3.86,
          ifelse (data_model3$Gewicht < 10, 4.39,
          ifelse (data_model3$Gewicht < 20, 4.81,
          ifelse (data_model3$Gewicht < 31.5, 6.34, 17.09)
      ))))
      

      结果如下:

      > data_model3
         Gewicht LIXshipping
      1        1        3.26
      2        2        3.86
      3        3        3.86
      4        4        3.86
      5        5        4.39
      6        6        4.39
      7        7        4.39
      8        8        4.39
      9        9        4.39
      10      10        4.81
      11      11        4.81
      12      12        4.81
      13      13        4.81
      14      14        4.81
      15      15        4.81
      16      16        4.81
      17      17        4.81
      18      18        4.81
      19      19        4.81
      20      20        6.34
      21      21        6.34
      22      22        6.34
      23      23        6.34
      24      24        6.34
      25      25        6.34
      26      26        6.34
      27      27        6.34
      28      28        6.34
      29      29        6.34
      30      30        6.34
      31      31        6.34
      32      32       17.09
      33      33       17.09
      34      34       17.09
      35      35       17.09
      36      36       17.09
      37      37       17.09
      38      38       17.09
      39      39       17.09
      40      40       17.09
      

      我删除了多余的条件(当分配给变量的值与前一个相同时)。你不需要像data_model3$Gewicht[i] &gt; 1 &amp; data_model3$Gewicht[i] &lt; 2 这样的双重保护,因为第一个条件已经在前面的if 语句中测试过了。

      请注意,当输入正好是 1、2、3 等时,您的原始代码不会执行任何操作,因为您只使用了严格的比较运算符 &lt;&gt;,但通常我们至少放置其中一个&lt;=&gt;= 保护所有案件。我认为这是一个错误并优化了它们。

      希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        您可以尝试以下方法:

        require(data.table)
        setDT(data_model3)
        data_model3[, LIXshipping:= ifelse(Gewicht < 2 & Gewicht != 1, 3.26,
                                           ifelse(Gewicht > 2 & Gewicht < 5 & !(Gewicht %in% c(3, 4)), 3.86,
                                                  ifelse(Gewicht > 5 & Gewicht < 10, 4.39,
                                                         ifelse(Gewicht > 10 & Gewicht < 20, 4.81,
                                                                ifelse(Gewicht > 20 & Gewicht < 31.5, 6.34, 17.09)))))]
        

        我根据您分配给它们的值缩短了一些类别(例如,您为类别 1 和 2 分配相同的运费值) 至于你在代码中做错了什么,你应该将值分配给data_model3$LIXshipping[i],所以data_model3$LIXshipping[i] &lt;- 4.81

        【讨论】:

          【解决方案5】:

          我忘记在我的代码中索引 data_model3$LIXshipping[i]。感谢@jogo 指出。

          for(i in 1:length(data_model3$Gewicht)){
                  if (data_model3$Gewicht[i] < 1){
                    data_model3$LIXshipping[i] <- 3.26 
                  }
                  else if (data_model3$Gewicht[i] > 1 & data_model3$Gewicht[i] < 2){
                    data_model3$LIXshipping[i] <- 3.26 
                  }
                  else if (data_model3$Gewicht[i] > 2 & data_model3$Gewicht[i] < 3){
                    data_model3$LIXshipping[i] <- 3.86 
                  }
                  else if (data_model3$Gewicht[i] > 3 & data_model3$Gewicht[i] < 4){
                    data_model3$LIXshipping[i] <- 3.86 
                  }
                  else if (data_model3$Gewicht[i] > 4 & data_model3$Gewicht[i] < 5){
                    data_model3$LIXshipping[i] <- 3.86 
                  }
                  else if (data_model3$Gewicht[i] > 5 & data_model3$Gewicht[i] < 10){
                    data_model3$LIXshipping[i] <- 4.39 
                  }
                  else if (data_model3$Gewicht[i] > 10 & data_model3$Gewicht[i] < 20){
                    data_model3$LIXshipping[i] <- 4.81 
                  }
                  else if (data_model3$Gewicht[i] > 20 & data_model3$Gewicht[i] < 31.5){
                    data_model3$LIXshipping[i] <- 6.34 
                  }
                  else 
                    data_model3$LIXshipping[i] <- 17.09 
          }
          

          【讨论】:

          • 但这可能不是解决问题的最佳方法。您至少可以使用矢量化 if else。
          • @jogo - 男孩,我喜欢那些单行字!很棒的代码打高尔夫球!
          猜你喜欢
          • 2020-06-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-01
          • 2016-04-23
          • 1970-01-01
          相关资源
          最近更新 更多