R-使用if语句重新组合变量

时间:2018-11-25 22:07:49

标签: r

我想将一个变量重新组合为一个新变量。

如果value为0,则新的也应为0。 如果值ist 999,则使其不存在,NA。 其他一切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 :(得分:3)

尝试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

if(condition)中,它应该是一个长度不是1的逻辑向量,请参见?"if"


例如,您可以避免使用ifelse

df$variable2 <- df$variable
df$variable2[df$variable2 == 999] <- NA
df$variable2[df$variable2 > 0] <- 1

答案 1 :(得分:2)

通过在子集符号内使用条件语句来避免同时使用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

答案 2 :(得分:2)

好像您想重新编码变量。您可以使用sjmisc-package来执行此操作(以及其他数据/变量转换),对于您的情况,可以使用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

help-file中也有很多示例,您可以在RStudio-Cheatsheet collection(或direct PDF-download here)上找到一个sjmisc备忘单。

答案 3 :(得分:1)

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

此一线代表您:

  

如果value为0,则新的也应为0。如果值999,则将其设为   失踪,不适用。其他一切1

好吧,它比@markus的第二个解决方案或@SPJ的解决方案(大多数是r-ish解决方案)要慢一些。

为什么要放弃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指出这一点! 奇怪的是我在最初的试用中没有意识到这一点。 但是,是的,您绝对正确!