在 R 中创建虚拟变量的简单方法
Simple way of creating dummy variable in R
我想知道如何简单地创建虚拟变量。我在 dummy 上发现了很多类似的问题,但它们要么是基于一些外部包,要么是技术性的。
我有这样的数据:
df <- data.frame(X=rnorm(10,0,1), Y=rnorm(10,0,1))
df$Z <- c(NA, diff(df$X)*diff(df$Y))
Z 在 df 中创建一个新变量,即 X 变化和 Y 变化的乘积。
现在我想在 df 中创建一个虚拟变量 D,如果:Z < 0 那么 D==1,如果 Z >0 那么 D==0。
我这样试过:
df$D <- NA
for(i in 2:10) {
if(df$Z[i] <0 ) {
D[i] ==1
}
if(df$Z[i] >0 ) {
D[i] ==0
}}
这是行不通的。
我想知道为什么上面的代码不起作用(使用简单的方法),以及如何在不使用任何外部包的情况下在 R 中创建虚拟变量,只需一点解释。
我们可以通过 df$Z < 0
创建一个逻辑向量,然后通过用 +
包装将其强制转换为二进制。
df$D <- +(df$Z <0)
或者正如@BenBolker 提到的,规范的选项是
as.numeric(df$Z < 0)
或
as.integer(df$Z < 0)
基准
set.seed(42)
Z <- rnorm(1e7)
library(microbenchmark)
microbenchmark(akrun= +(Z < 0), etienne = ifelse(Z < 0, 1, 0),
times= 20L, unit='relative')
# Unit: relative
# expr min lq mean median uq max neval
# akrun 1.00000 1.00000 1.000000 1.00000 1.00000 1.000000 20
# etienne 12.20975 10.36044 9.926074 10.66976 9.32328 7.830117 20
尝试:
df$D<-ifelse(df$Z<0,1,0)
df
X Y Z D
1 -0.1041896 -1.11731404 NA NA
2 -1.4286604 1.42523717 -3.36753491 1
3 0.3931643 -0.05525477 -2.69719691 1
4 -0.2236541 1.64531526 -1.04894297 1
5 1.1725167 0.80063291 -1.17932089 1
6 0.7571427 0.64072381 0.06642209 0
7 0.4929186 1.25125268 -0.16131645 1
8 0.9715885 -0.54755653 -0.86103574 1
9 -0.2962052 -1.37459521 1.04851438 0
10 -1.4838675 -0.85788632 -0.61367565 1
ifelse
函数有 3 个参数:要计算的条件 df$Z<0
,条件为 TRUE
时的值:1 和条件为 [=14= 时的值] : 0。该函数是矢量化的,因此在这种情况下效果很好。
你可以试试
df$D[df$Z<0]<-1
df$D[df$Z>0]<-0
但是你应该考虑Z可以为0的可能性
我想知道如何简单地创建虚拟变量。我在 dummy 上发现了很多类似的问题,但它们要么是基于一些外部包,要么是技术性的。
我有这样的数据:
df <- data.frame(X=rnorm(10,0,1), Y=rnorm(10,0,1))
df$Z <- c(NA, diff(df$X)*diff(df$Y))
Z 在 df 中创建一个新变量,即 X 变化和 Y 变化的乘积。 现在我想在 df 中创建一个虚拟变量 D,如果:Z < 0 那么 D==1,如果 Z >0 那么 D==0。
我这样试过:
df$D <- NA
for(i in 2:10) {
if(df$Z[i] <0 ) {
D[i] ==1
}
if(df$Z[i] >0 ) {
D[i] ==0
}}
这是行不通的。 我想知道为什么上面的代码不起作用(使用简单的方法),以及如何在不使用任何外部包的情况下在 R 中创建虚拟变量,只需一点解释。
我们可以通过 df$Z < 0
创建一个逻辑向量,然后通过用 +
包装将其强制转换为二进制。
df$D <- +(df$Z <0)
或者正如@BenBolker 提到的,规范的选项是
as.numeric(df$Z < 0)
或
as.integer(df$Z < 0)
基准
set.seed(42)
Z <- rnorm(1e7)
library(microbenchmark)
microbenchmark(akrun= +(Z < 0), etienne = ifelse(Z < 0, 1, 0),
times= 20L, unit='relative')
# Unit: relative
# expr min lq mean median uq max neval
# akrun 1.00000 1.00000 1.000000 1.00000 1.00000 1.000000 20
# etienne 12.20975 10.36044 9.926074 10.66976 9.32328 7.830117 20
尝试:
df$D<-ifelse(df$Z<0,1,0)
df
X Y Z D
1 -0.1041896 -1.11731404 NA NA
2 -1.4286604 1.42523717 -3.36753491 1
3 0.3931643 -0.05525477 -2.69719691 1
4 -0.2236541 1.64531526 -1.04894297 1
5 1.1725167 0.80063291 -1.17932089 1
6 0.7571427 0.64072381 0.06642209 0
7 0.4929186 1.25125268 -0.16131645 1
8 0.9715885 -0.54755653 -0.86103574 1
9 -0.2962052 -1.37459521 1.04851438 0
10 -1.4838675 -0.85788632 -0.61367565 1
ifelse
函数有 3 个参数:要计算的条件 df$Z<0
,条件为 TRUE
时的值:1 和条件为 [=14= 时的值] : 0。该函数是矢量化的,因此在这种情况下效果很好。
你可以试试
df$D[df$Z<0]<-1
df$D[df$Z>0]<-0
但是你应该考虑Z可以为0的可能性