2012-01-24 15 views
6

Tengo un marco de datos de 9 columnas que consta de un inventario de factores. Cada fila puede tener las 9 columnas llenas (como en esa fila tiene 9 "cosas"), pero la mayoría no (la mayoría tiene entre 3 y 4). Las columnas tampoco son específicas, como si el elemento 200 aparece en las columnas 1 y 3, es lo mismo. Me gustaría crear una matriz que sea binaria para cada fila que incluya todos los factores.¿Cómo crear una matriz binaria de inventario por fila? (R)

Ex (abreviado a 4 columnas sólo para señalar al otro lado)

R1 3 4 5 8 
R2 4 6 7 NA 
R3 1 5 NA NA 
R4 2 6 8 9 

debe convertirse en

 1 2 3 4 5 6 7 8 9 
r1 0 0 1 1 1 0 0 1 0 
r2 0 0 0 1 0 1 1 0 0 
r3 1 0 0 0 1 0 0 0 0 
r4 0 1 0 0 0 1 0 1 1 

He mirado en writeBin/readBin, K-agrupación (que es algo que Me gustaría hacerlo, pero primero necesito deshacerme de las NA), clustering difuso, agrupamiento de etiquetas. Simplemente perdido acerca de qué dirección tomar.

He intentado escribir dos bucles para extraer los datos de la matriz por columna/fila y luego guardar 0 y 1 respectivamente en una nueva matriz, pero creo que hubo problemas de alcance.

Ustedes son los mejores. ¡Gracias!

Respuesta

5

Aquí es una solución de base R:

# Read in the data, and convert to matrix form 
df <- read.table(text = " 
3 4 5 8 
4 6 7 NA 
1 5 NA NA 
2 6 8 9", header = FALSE) 
m <- as.matrix(df) 

# Create a two column matrix containing row/column indices of cells to be filled 
# with 'one's 
id <- cbind(rowid = as.vector(t(row(m))), 
      colid = as.vector(t(m))) 
id <- id[complete.cases(id), ] 

# Create output matrix 
out <- matrix(0, nrow = nrow(m), ncol = max(m, na.rm = TRUE)) 
out[id] <- 1 
#  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
# [1,] 0 0 1 1 1 0 0 1 0 
# [2,] 0 0 0 1 0 1 1 0 0 
# [3,] 1 0 0 0 1 0 0 0 0 
# [4,] 0 1 0 0 0 1 0 1 1 
+0

+1 Esa frase me deja boquiabierto. –

+0

Josh, esto es impresionante. ¿Hay un término para lo que se llama? Estaba pensando en la matriz de inventario, la matriz de elementos o la matriz binaria, pero todos parecen relacionarse con otras ideas. –

+0

Gracias. Pienso en * el resultado * como una matriz de indicadores (después de la [función de indicador] (http://en.wikipedia.org/wiki/Indicator_function)) de una matriz de presencia/ausencia (porque codifica si o no cada artículo está presente o ausente en una fila dada). Sin embargo, no estoy seguro si hay un nombre general aceptado para ello. –

3

Esto debe hacer el truco:

# The Incantation 
options(stringsAsFactors = FALSE) 

library(reshape2) 

# Your example data 
dat <- data.frame(id = c("R1", "R2", "R3", "R4"), 
        col1 = c(3, 4, 1, 2), 
        col2 = c(4, 6, 5, 6), 
        col3 = c(5, 7, NA, 7), 
        col4 = c(8, NA, NA, 9) 
) 

# Melt it down 
dat.melt <- melt(dat, id.var = "id") 

# Cast it back out, with the row IDs remaining the row IDs 
# and the values of the columns becoming the columns themselves. 
# dcast() will default to length to aggregate records - which means 
# that the values in this data.frame are a count of how many times 
# each value occurs in each row's columns (which, based on this data, 
# seems to be capped at just once). 
dat.cast <- dcast(dat.melt, id ~ value) 

El resultado:

dat.cast 
    id 1 2 3 4 5 6 7 8 9 NA 
1 R1 0 0 1 1 1 0 0 1 0 0 
2 R2 0 0 0 1 0 1 1 0 0 1 
3 R3 1 0 0 0 1 0 0 0 0 2 
4 R4 0 1 0 0 0 1 1 0 1 0 
1

Estas son todas las grandes respuestas. Pensé que contribuiría con la solución original que escribí, que un amigo mío modificó para que realmente funcione.

for(i in seq(nrow(x))) 
    for(j in seq(ncol(x))) 
    if(!is.na(x[i,j])) { y[i, x[i,j]] = 1 } 

Dos bucles funcionan después de establecer algunos parámetros anteriores, pero es increíblemente lento. ¡Parece que estas otras soluciones funcionan mucho más rápido!

Cuestiones relacionadas