r编程---条件赋值产生意外结果

时间:2015-12-22 15:39:12

标签: r

我有一个数据框,我需要根据其他两个变量的值创建一个新变量。结果不符合我的期望。这就是我所拥有的:

d <- data.frame(
     customer = rep(c("a","b"),3),
     prod1 = c("tea", "gum", "candy", "tea","snack", "bar"),
     prod2 = c(NA, NA, "juice", NA,NA,"cocoa")

)

d <- d[order(d$customer),]

> d
  customer prod1 prod2
1        a   tea  <NA>
3        a candy juice
5        a snack  <NA>
2        b   gum  <NA>
4        b   tea  <NA>
6        b   bar cocoa

我想创建另一个变量,只有当!is.na(prod2)为真时才接受prod2的值,否则取值prod1。我尝试了两种方法并创建了两个不同的变量来比较结果:

ifelse(!is.na(d$prod2),
   d$products1 <- d$prod2, d$products1 <- d$prod1)

d$products2[is.na(d$prod2)]  <- d$prod1[is.na(d$prod2)]
d$products2[!is.na(d$prod2)] <- d$prod2[!is.na(d$prod2)]

我明白了:

> d
  customer prod1 prod2 products1 products2  i.wanted
1        a   tea  <NA>       tea         5     tea  
3        a candy juice     candy         2     juice
5        a snack  <NA>     snack         4     snack
2        b   gum  <NA>       gum         3     gum
4        b   tea  <NA>       tea         5     tea
6        b   bar cocoa       bar         1     cocoa

我想要的是列i.wanted但不是我得到的。 ifelse条件通过简单地从prod1获取值而不从prod2获取任何值来创建products1。第二种方法返回数字向量。

任何帮助表示赞赏!!!

2 个答案:

答案 0 :(得分:1)

这可能是因为您将一个TRUE / FALSE值向量传递给ifelse函数。如果您使用多个逻辑值的变量进行条件分支,那么R不会喜欢它 - 因为哪个是它应该考虑的那个?通常它会假设向量中的第一个TRUE / FALSE值并给出警告。无论如何,这是使用apply函数执行此操作的一种方法:

d$i.wanted <- apply(d, 1, function(x){
  if(!is.na(x[3])){
    return(x[3])
  } else {
    return(x[2])
  }
})

这里我逐行遍历d,并检查第三个变量,即prod2列中的值是否不是na,如果是,则返回。如果是NA,则返回第二个变量,即prod1的值。

此外,你的第二个解决方案实际上几乎是正确的,你推测索引是正确的,它可能给你问题的原因是它试图结合两个不同的因子变量,通过存储存储分类变量每个唯一值作为“级别”:

> d$prod1
[1] tea   candy snack gum   tea   bar  
Levels: bar candy gum snack tea
> d$prod2
[1] <NA>  juice <NA>  <NA>  <NA>  cocoa
Levels: cocoa juice 

矢量索引那些级别,即d $ prod1是5,2,4,3 ......等等。因为酒吧是第5级,糖果是第2级,依此类推。 然后你可以开始明白为什么这可能在prod 1中存在问题,有5个级别1:5,而在prod2中,有两个级别1:2。在prod1中,任何“bar”都存储为1,但在prod2中,任何cocoa也存储为1.如果你修改了你编写的代码,将列视为字符串的向量而不是因子,那么你的两行将是工作:

d$products2[is.na(d$prod2)]  <- as.character(d$prod1)[which(is.na(d$prod2))]
d$products2[!is.na(d$prod2)] <- as.character(d$prod2)[which(!is.na(d$prod2))]

希望有所帮助! 乙

答案 1 :(得分:0)

沃德感谢指出使用字符向量而不是默认因子。你的条件包括你的解决方案。但是,我尝试了不同的ifelse,这就是我发现的:

以下DID无法正常工作:

ifelse(!is.na(d$prod2),
       d$products1 <- as.character(d$prod2), 
       d$products1 <- as.character(d$prod1)) 

这里有两个不同的条件产生了预期的结果:

d$products2 <- ifelse(!is.na(d$prod2),
               d$products2 <- as.character(d$prod2), 
               d$products2 <- as.character(d$prod1)) 

d$products3 <- ifelse(!is.na(d$prod2),
               as.character(d$prod2), 
               as.character(d$prod1)) 

从上面的结果中,我发现在需要ifelse条件和as.character之前我需要一个赋值。 d $ products1和d $ products2的创建方式完全相同,只是d $ products2在ifelse条件之前有一个赋值运算符。

这里是结果(产品2,3和4都很好):

> d
  customer prod1 prod2 products1 products2 products3 products4
1        a   tea  <NA>       tea       tea       tea       tea
3        a candy juice     candy     juice     juice     juice
5        a snack  <NA>     snack     snack     snack     snack
2        b   gum  <NA>       gum       gum       gum       gum
4        b   tea  <NA>       tea       tea       tea       tea
6        b   bar cocoa       bar     cocoa     cocoa     cocoa