transformar columnas en columnas codificadas en binario en R
Sep 02 2020
Tengo algunas variables nominales codificadas como enteros (no ordinales), que me gustaría codificar como binarias (¡ni dummies ni hot!). El siguiente código es lo que se me ocurrió (adaptado de otro código que encontré). ¿Es este un enfoque válido / escalable? ¡Gracias!
library(binaryLogic)
df <- data.frame(x1 = c(1, 1, 2, 3), x2 = c(1, 2, 3, 4))
encode_binary <- function(x, name = "binary_") {
x2 <- as.binary(x)
maxlen <- max(sapply(x2, length))
x2 <- lapply(x2, function(y) {
l <- length(y)
if (l < maxlen) {
y <- c(rep(0, (maxlen - l)), y)
}
y
})
d <- as.data.frame(t(as.data.frame(x2)))
rownames(d) <- NULL
colnames(d) <- paste0(name, 1:maxlen)
d
}
df <- cbind(df, encode_binary(df[["x1"]], name = "binary_x1_"))
df <- cbind(df, encode_binary(df[["x2"]], name = "binary_x2_"))
df
Respuestas
1 minem Sep 02 2020 at 15:23
Si probamos en un vector más grande, su enfoque es bastante lento:
test_vec <- 1:1e5
system.time(v1 <- encode_binary(test_vec, name = "binary_x1_"))
# user system elapsed
# 22.23 0.08 22.37
Basado en esta pregunta SO , logré escribir un código que funciona mucho más rápido:
encode_binary2 <- function(x, name = "binary_") {
m <- sapply(x, function(x) rev(as.integer(intToBits(x))))
tm <- t(m)
# remove empty bit cols
i <- which(colSums(tm) != 0L)[1]
tm <- tm[, i:ncol(tm)]
# save to data.frame
d <- as.data.frame(tm)
rownames(d) <- NULL
colnames(d) <- paste0(name, 1:ncol(d))
d
}
system.time(v2 <- encode_binary2(test_vec, name = "binary_x1_"))
# user system elapsed
# 0.61 0.02 0.63
# test that results are equal:
all.equal(v1, v2)
# [1] TRUE