R - использовать оператор if для перегруппировки переменной - PullRequest
0 голосов
/ 26 ноября 2018

Я хочу перегруппировать переменную в новую.

Если значение равно 0, новая тоже должна быть 0.Если значение равно 999, то пропустить его, нет данных.Все остальное 1

Это моя попытка:

id <- 1:10
variable <- c(0,0,0,1,2,3,4,5,999,999)
df <- data.frame(id,variable)

df$variable2 <- 
  if (df$variable == 0) {
    df$variable2 = 0
  } else if (df$variable == 999){
    df$variable2 = NA
  } else {
    df$variable2 = 1
  }

И это сообщение об ошибке:

В if (df $ variable == 0) {:условие имеет длину> 1, и будет использоваться только первый элемент

Довольно простой вопрос, но я обычный пользователь.Заранее спасибо!

Ответы [ 4 ]

0 голосов
/ 26 ноября 2018

Похоже, вы хотите перекодировать вашу переменную.Вы можете сделать это (и другие преобразования данных / переменных) с sjmisc-пакетом , в вашем случае с rec() -командой:

id <- 1:10
variable <- c(0,0,0,1,2,3,4,5,999,999)
df <- data.frame(id,variable)

library(sjmisc)
rec(df, variable, rec = c("0=0;999=NA;else=1"))
#>    id variable variable_r
#> 1   1        0          0
#> 2   2        0          0
#> 3   3        0          0
#> 4   4        1          1
#> 5   5        2          1
#> 6   6        3          1
#> 7   7        4          1
#> 8   8        5          1
#> 9   9      999         NA
#> 10 10      999         NA

# or a single vector as input
rec(df$variable, rec = c("0=0;999=NA;else=1"))
#> [1]  0  0  0  1  1  1  1  1 NA NA

Есть много примеров, такжев справочном файле , и вы можете найти sjmisc-cheatsheet в коллекции RStudio-Cheatsheet (или прямая PDF-загрузка здесь ).

0 голосов
/ 26 ноября 2018

Может быть проще избежать использования оператора if / else, используя условные операторы в нотации подмножества:

, когда df$variable равно нулю, измените его на ноль

df$variable[df$variable==0] <- 0

когда df$variable равно 999, измените его на NA

df$variable[df$variable==999] <- NA

, если df$variable больше 0 и не равно NA, измените его на 1

df$variable[df$variable>0 & is.na(df$variable) == 'FALSE'] <- 1
0 голосов
/ 26 ноября 2018
df$variable2 <- sapply(df$variable, 
                       function(el) if (el == 0) {0} else if (el == 999) {NA} else {1})

Эта однострочная строка отражает ваше:

Если значение равно 0, новое также должно быть равно 0.Если значение равно 999, то пропустить его, нет данных.Все остальное 1

Ну, это немного медленнее, чем второе решение @ markus или решение @ SPJ, которые являются большинством новых решений.

Почему нужно убирать рукиот ifelse

tt <- c(TRUE, FALSE, TRUE, FALSE)
a <- c("a", "b", "c", "d")
b <- 1:4
ifelse(tt, a, b) ## [1] "a" "2" "c" "4"
# totally perfect and as expected!

df <- data.frame(a=a, b=b, c=tt)
df$d <- ifelse(df$c, df$a, df$b)
## > df
##   a b     c d
## 1 a 1  TRUE 1
## 2 b 2 FALSE 2
## 3 c 3  TRUE 3
## 4 d 4 FALSE 4

######### This is wrong!! ##########################
## df$d is not [1] "a" "2" "c" "4"
## the problem is that 
## ifelse(df$c, df$a, df$b)
## returns for each TRUE or FALSE the entire
## df$a or df$b intead of treating it like a vector.
## Since the last df$c is FALSE, df$b is returned
## Thus we get df$b for df$d.
## Quite an unintuitive behaviour.
##
## If one uses purely vectors, ifelse is fine.
## But actually df$c, df$a, df$b should be treated each like a vector.
## However, `ifelse` does not.
## No warnings that using `ifelse` with them will lead to a 
## totally different behaviour.
## In my view, this is a design mistake of `ifelse`.
## Thus I decided myself to abandon `ifelse` from my set of R commands.
## To avoid that such kind of mistakes can ever happen.
#####################################################

Как правильно заметил @Parfait, это была неверная интерпретация.Проблема заключалась в том, что df $ a обрабатывался во фрейме данных как фактор.

df <- data.frame(a=a, b=b, c=tt, stringsAsFactor = F)
df$d <- ifelse(df$c, df$a, df$b)
df

Дает правильный результат.

  a b     c d
1 a 1  TRUE a
2 b 2 FALSE 2
3 c 3  TRUE c
4 d 4 FALSE 4

Спасибо @Parfait за указание на это!Странно, что я не узнал этого в моих первых испытаниях.Но да, ты абсолютно прав!

0 голосов
/ 26 ноября 2018

Попробуйте ifelse

df$variable2 <- ifelse(df$variable == 999, NA, ifelse(df$variable > 0, 1, 0))
df
#   id variable variable2
#1   1        0         0
#2   2        0         0
#3   3        0         0
#4   4        1         1
#5   5        2         1
#6   6        3         1
#7   7        4         1
#8   8        5         1
#9   9      999        NA
#10 10      999        NA

Когда вы делаете df$variable == 0, то вывод / condition равен

#[1]  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

, где он должен быть логическим по длине-1вектор, который не является NA в if(condition), см. ?"if".


Вы можете избежать, например, ifelse, например

df$variable2 <- df$variable
df$variable2[df$variable2 == 999] <- NA
df$variable2[df$variable2 > 0] <- 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...