0

我有一个如下所示的数据框:

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

关于发生了什么的任何线索?

4

5 回答 5

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 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 ')
于 2013-02-20T09:35:20.063 回答
4

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

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

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

于 2013-02-20T09:36:15.317 回答
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))

在这里,您有 5 个唯一值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)
于 2013-02-20T10:21:59.347 回答
3

您需要在 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)
}
于 2013-02-20T09:32:11.887 回答
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
于 2013-02-20T09:39:35.547 回答