2016-10-11 3 views
0

У меня возникла проблема с несколькими операторами if. Вывод всегда берется из первого условия, даже если условие неверно. Может ли кто-нибудь указать, что я делаю неправильно?Вложенные операторы if - R

код:

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 

Это может быть compleately основной вопрос для некоторых из вас .. но я понятия не имею, как это исправить.
Andraz

+5

Использование 'cut' вместо вложенного' if/else'.Кроме того, вы можете использовать векторизованный 'ifelse' – akrun

+0

Возможный дубликат http://stackoverflow.com/questions/29235377/changing-continuous-ranges-to-categorical-in-r – zx8754

+1

' data_model3 $ LIXshipping <- ... 'is меняя весь столбец. – jogo

ответ

3

Это можно сделать с помощью одной линии (+ одна строки данных):

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))) 
-1

Я забыл индекс 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 
} 
+3

Но это может быть не лучший способ его решения. Вы могли бы хотя бы использовать векторизованный if else. –

+1

@jogo - Мальчик, я обожаю те однострочники! Хороший код-гольф! – Ricardo

0

Это непосредственно не отвечая на вопрос, но я хотел бы представить, что код с векторизованного ifelse будет выглядеть, как это было предложено @akrun и, плюс @ Тим несколько оптимизаций шахты:

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] > 1 & data_model3$Gewicht[i] < 2, потому что первое условие уже было проверено в предыдущем заявлении if.

Обратите внимание, что исходный код ничего не делает, когда вход ровно 1, 2, 3 и так далее, потому что вы использовали строгие операторы сравнения < и >, но обычно мы ставим по крайней мере, один из <= и >= для защиты всех случаев. Я предположил, что это была ошибка и оптимизировала их.

Надеюсь, это поможет.

0

Вы можете попробовать следующее:

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] <- 4.81.

3

Я бы поставил правила в таблице ...

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)) 
Смежные вопросы