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

R中的If-Then循环不识别条件语句,r,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.2

我有一个数据框,看起来像下面这样:

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

data$Z您需要在x满足这些条件的相同索引中将Z设置为所需的值,因此:

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

data$Z此处使用
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进行此类操作。您保持了业务逻辑的清晰,并且它与矢量化版本(直觉)一样快速

库(sqldf)

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

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

data$Z它只使用一个
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
的情况下工作(多亏了数学):


到目前为止,所有这些答案都假设您只有3个值(正确地说,没有理由假设其他值)

但是,假设您可能有3个以上的值,在这种情况下可以使用
merge
,如下所示:

# assuming this is your data (dummy)
set.seed(45)
df <- data.frame(x=rep(1:5, each=5), y=sample(25))
现在,您可以使用
merge
作为:

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

谁有两个拇指却觉得自己很笨?“这家伙,”他说,“这是最不地道的回答。学习使用矢量化函数而不是
进行循环。这样你的代码会运行得更快。是的,我不完全理解R社区对
for
循环的普遍憎恨,但我确实倾向于认为像
ifelse
这样的事情更适合这些情况,我主要是在纠正OP原始代码中的特定缺陷。没有普遍的憎恨,但这种循环效率极低。但是我明白你纠正具体缺陷的意义,这就是为什么我没有投反对票的原因。@Roland在这种情况下,由于我正在处理的具体问题,矢量化所获得的速度不是工作时间,它将花费像ifelse这样的适当布局。这里有一个地方,我不愿意为了以微小单位测量的速度而牺牲清晰度。我不认为这会“更好”。它在代码中保存了几个字符,…+1!我喜欢X-1的把戏!即使我们失去了逻辑(我们隐藏了业务规则)!
# assuming this is your data (dummy)
set.seed(45)
df <- data.frame(x=rep(1:5, each=5), y=sample(25))
# 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(df, key, by="x", all=T)