从整个数据集中的因子级别创建多个二进制列

时间:2018-03-19 04:07:13

标签: r binary lapply

我一直在处理一个目前包含89个列的数据集,其中43个因子列的级别最多为15个。我想知道是否有一种方法可以抓取所有列 - 找到因子变量并将它们分解为二进制列。到目前为止,我已经能够在stackoverflow上从我的搜索中找到一些代码,但是我还没有能够以正确的方式将它们组合在一起。

首先,我将使用starwars数据集

data <- starwars
lapply(data, class)
data$hair_color <- as.factor(data$hair_color)
data$skin_color <- as.factor(data$skin_color)
data$eye_color <- as.factor(data$eye_color)

要将单个变量分解为二进制,我将使用以下

for (i in unique(data$hair_color)){
data[,paste0(i)]=ifelse(data$hair_color==i,1,0)
}

我可以将列放在可以使其更容易的列表中

w <- which( sapply( data, class ) == 'factor' )

创建上面的函数(我无法超越这一点)

createbin <- function(x){
  for (i in unique(x)){
    data[,paste0(i)]=ifelse(x==i,1,0)
  }
}

现在将其应用于整个列表

lapply(data[,w], createbin)

这不起作用,所以任何帮助将不胜感激

1 个答案:

答案 0 :(得分:1)

我不完全确定你要做什么。也许比factor数据集中starwars级更少的简单样本数据集会有所帮助。

无论哪种方式,我认为model.matrix可能是您问题的关键。

例如,我们可以首先为所有factor级别生成二进制模型矩阵:

w <- which(sapply(data, class) == 'factor');

# Create model matrix for all factors
df <- as.data.frame.matrix(model.matrix(
    as.formula(sprintf("name ~  0 + %s", paste0(names(w), collapse = "+"))),
    data = data));

对于最终data.frame,我们然后cbind原始data.frame减去factor列,以及所有factor级别的模型矩阵。

df <- cbind.data.frame(data[, -w], df);

更新

为了说明,让我们举一个更简单的例子。

# Sample data
data <- data.frame(
    x = 1:12,
    y = 11:22,
    z = gl(3, 4, 12, c("factorA", "factorB", "factorC")));
#    x  y       z
#1   1 11 factorA
#2   2 12 factorA
#3   3 13 factorA
#4   4 14 factorA
#5   5 15 factorB
#6   6 16 factorB
#7   7 17 factorB
#8   8 18 factorB
#9   9 19 factorC
#10 10 20 factorC
#11 11 21 factorC
#12 12 22 factorC

所有factor列的索引。

w <- which(sapply(data, class) == 'factor');
w;
#z
#3

构建模型矩阵:

# Model matrix
df <- as.data.frame.matrix(model.matrix(
    as.formula(sprintf("x ~  0 + %s", paste0(names(w), collapse = "+"))),
    data = data));

具有二进制data.frame级别的最终factor

df <- cbind.data.frame(data[, -w], df);
#    x  y zfactorA zfactorB zfactorC
#1   1 11        1        0        0
#2   2 12        1        0        0
#3   3 13        1        0        0
#4   4 14        1        0        0
#5   5 15        0        1        0
#6   6 16        0        1        0
#7   7 17        0        1        0
#8   8 18        0        1        0
#9   9 19        0        0        1
#10 10 20        0        0        1
#11 11 21        0        0        1
#12 12 22        0        0        1