R中的If-Then循环不识别条件语句

时间:2013-02-20 09:30:03

标签: r

我有一个类似于以下内容的数据框:

X Y
1 3
1 7
1 9
2 12
2 4
2 8 
3 11
3 3
3 5

我想创建一个新的变量Z,如果X = 1则为0.25,如果X = 2则为0.75,如果X = 3,则为0.95。

我尝试了下面的代码,它创建了一个变量Z然后遍历X,检查X是否是某个值,然后将Z设置为相应的正确值。例如:

data$Z <- 0
for (i in 1:length(data$X)){
   if (data$X[i]==1) {data$Z <- 0.25)
   if (data$X[i]==2) {data$Z <- 0.50)
   if (data$X[i]==2) {data$Z <- 0.95)
}

问题是由于某种原因,条件触发器在此代码中没有被触发。如果我只使用第一个if语句运行它,那么Z的所有都设置为0.25。只有前两个,它们都是0.50等等。

有关正在发生的事情的任何线索?

5 个答案:

答案 0 :(得分:4)

请使用ifelse,因为它是矢量化的:

transform(dat, Z=ifelse(X==1,0.25,ifelse(X==2,0.75,0.95)))
 X  Y    Z
1 1  3 0.25
2 1  7 0.25
3 1  9 0.25
4 2 12 0.75
5 2  4 0.75
6 2  8 0.75
7 3 11 0.95
8 3  3 0.95
9 3  5 0.95

PS:这里我假设X只取3个值。

修改

我喜欢使用sql案例进行此类操作。您可以清楚地了解业务逻辑,它作为矢量化版本(直觉)很快

library(sqldf)
dat$newX <- sqldf('SELECT CASE X 
       WHEN 1  THEN 0.25
       WHEN 2 THEN 0.5
       ELSE 0.95
       END AS newX
      FROM dat ')

答案 1 :(得分:4)

在这个简单的例子中,最简单的方法是使用子集:

data$Z <- 0.25
data$Z[data$X==2] <- 0.50
data$Z[data$X==3] <- 0.95

不需要任何循环或if / else语句。

答案 2 :(得分:4)

到目前为止,所有这些答案都假设您只有3个值(这是正确的,没有理由不这样做)。

但是,假设您的值可能超过3个,那么在这种情况下可以使用merge

# assuming this is your data (dummy)
set.seed(45)
df <- data.frame(x=rep(1:5, each=5), y=sample(25))

在这里,您有x的五个唯一值。您可以使用要为X的每个值生成附加列的值创建data.frame

# here for each unique x, there is a value (just for example, randomly generated)
# equivalent to 0.25, 0.5 and 0.95 in your case
key <- data.frame(x=1:5, val=runif(5))

现在,您可以将merge用作:

merge(df, key, by="x", all=T)

答案 3 :(得分:3)

您需要将Z设置为您希望在相同索引的值,其中x符合这些条件,因此:

data$Z <- 0
for (i in 1:length(data$X)){
   if (data$X[i]==1) {data$Z[i] <- 0.25)
   if (data$X[i]==2) {data$Z[i] <- 0.50)
   if (data$X[i]==3) {data$Z[i] <- 0.95)
}

答案 4 :(得分:3)

它仅适用于一个ifelse命令:

transform(dat, Z = ifelse(X == 3, 0.95, 0.25 + 0.5 * (X - 1)))

  X  Y    Z
1 1  3 0.25
2 1  7 0.25
3 1  9 0.25
4 2 12 0.75
5 2  4 0.75
6 2  8 0.75
7 3 11 0.95
8 3  3 0.95
9 3  5 0.95

它甚至可以在没有任何ifelse的情况下工作(感谢数学):

transform(dat, Z = 0.25 + round(0.50 * (X - 1) ^ .48, 2))

  X  Y    Z
1 1  3 0.25
2 1  7 0.25
3 1  9 0.25
4 2 12 0.75
5 2  4 0.75
6 2  8 0.75
7 3 11 0.95
8 3  3 0.95
9 3  5 0.95