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