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



我有一个数据帧,看起来如下所示:

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,等等

有关于发生了什么的线索吗?

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

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

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

到目前为止,所有这些答案都假设您只有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有五个唯一的值。您可以创建一个data.frame,其中包含您想要为X的每个值生成一个附加列的值:

# 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)

此处使用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

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

编辑

我喜欢使用sql case进行此类操作。你保持清晰的业务逻辑,它就像矢量化版本(直觉)一样快

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 ')

您需要在相同的索引处将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)
}

它只适用于一个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

最新更新