2015-10-05 4 views
1

У меня есть данные, как показано ниже. Я хочу новый столбец под названием accuracy_level. Как я могу это сделать? Я пробовал if, но это не сработало.r data.frame создать условный столбец

Если

  • accuracy_percentage находится в пределах +/- 10%, то accuracy_level будет "Хорошо"
  • accuracy_percentage находится в пределах +/- 30% и за ее пределами +/- 10%, то accuracy_level будет " Bad»
  • accuracy_percentage находится за пределами +/- 30%, то accuracy_level будет "Худшие"

Вот мой код:

actuals=seq(0,10,0.1) 
forecast=seq(10,0,-0.1) 
data1=data.frame(actuals,forecast) 
data1$diff=data1$actuals-data1$forecast 
data1$accuracy_percentage=(data1$diff/data1$actuals)*100 
if((data1$accuracy_percentage < 10)&(data1$accuracy_percentage > -10),data1$accuracy_level="good",) 
+0

Вы можете использовать 'ifelse' вместо' if/else' или лучше использовать 'cut' и указывать' label' – akrun

+0

, первая строка вашего df имеет значение 'inf'. '0.0 10.0 -10.0 -Inf' –

+0

Лучшая практика заключается в том, чтобы использовать пробел, чтобы вы и другие могли читать ваш код, и вы случайно не выполняете' x <-1' при попытке проверить 'x <-1' – Frank

ответ

3
data1$accuracy_level <- cut(abs(data1$accuracy_percentage), c(0, 10, 30, Inf), c("Good", "Bad", "Worst"), include.lowest=T) 
# actuals forecast diff accuracy_percentage accuracy_level 
# 19  1.8  8.2 -6.4   -355.55556   Worst 
# 71  7.0  3.0 4.0   57.14286   Worst 
# 57  5.6  4.4 1.2   21.42857   Bad 
# 17  1.6  8.4 -6.8   -425.00000   Worst 
# 92  9.1  0.9 8.2   90.10989   Worst 
# 91  9.0  1.0 8.0   88.88889   Worst 
# 13  1.2  8.8 -7.6   -633.33333   Worst 
# 79  7.8  2.2 5.6   71.79487   Worst 
# 44  4.3  5.7 -1.4   -32.55814   Worst 
# 51  5.0  5.0 0.0    0.00000   Good 

Использование cut даст вам возможность повысить скорость и масштабируемость. Мы находим интервалы абсолютных значений, abs, процент точности в зависимости от точек разреза c(0, 10, 30, Inf). И поставьте ярлыки для групп. Мы также добавляем аргумент include.lowest=TRUE для 0.000 случаев, которые падают на нижний предел наших точек разреза.

Вложенные ifelse утверждения используются, потому что их легко понять при считывании. Но если вам нужно было вложить 10 различных условий, это могло бы легко выйти из-под контроля.

В качестве примечания, если мы не требовали новых имен ярлыков, мы могли бы использовать связанную функцию findInterval, которая по существу делала бы то же самое с разницей назначения целочисленных значений в качестве вывода (то есть 1 2 3 4..).

2

Я использовал соединение ifelse

data1$accuracy_category <- ifelse(abs(data1$accuracy_percentage)<10, "Good", 
            ifelse(abs(data1$accuracy_percentage)<30, "Bad", "Worst")) 

дает

> head(data1) 
    actuals forecast diff accuracy_percentage accuracy_category 
1  0.0  10.0 -10.0    -Inf    Worst 
2  0.1  9.9 -9.8   -9800.000    Worst 
3  0.2  9.8 -9.6   -4800.000    Worst 
4  0.3  9.7 -9.4   -3133.333    Worst 
5  0.4  9.6 -9.2   -2300.000    Worst 
6  0.5  9.5 -9.0   -1800.000    Worst 

и как указывал @ пьер-Lafortune, это легче читать, но менее производительным. В духе Knuth Я провел несколько тестов. С вашим начальным набором:

> system.time(data1$accuracy_category <- ifelse(abs(data1$accuracy_percentage)<10, "Good", 
+ ifelse(abs(data1$accuracy_percentage)<30, "Bad", "Worst"))) 
    user system elapsed 
     0  0  0 
> system.time(data1$accuracy_level <- cut(abs(data1$accuracy_percentage), c(0, 10, 30, Inf), c("Good", "Bad", "Worst"), include.lowest=T)) 
    user system elapsed 
    0.000 0.000 0.001 

, но это на самом деле не говорит. Так что давайте провернуть его :) С

actuals=seq(0,100000,0.1) 
forecast=seq(100000,0,-0.1) 

Я получил

> system.time(data1$accuracy_category <- ifelse(abs(data1$accuracy_percentage)<10, "Good", 
+ ifelse(abs(data1$accuracy_percentage)<30, "Bad", "Worst"))) 
    user system elapsed 
    0.776 0.060 0.840 
> system.time(data1$accuracy_level <- cut(abs(data1$accuracy_percentage), c(0, 10, 30, Inf), c("Good", "Bad", "Worst"), include.lowest=T)) 
    user system elapsed 
    0.152 0.003 0.155 

который не показать, что cut будет гораздо более производительным, как вы масштабы. Все это говорит о том, что cut более изящный, если не менее читаемый, и я поддержал его ответ :) ymmv.

+2

Дох. хороший улов. –

Смежные вопросы