Как создать бинарную матрицу запасов в строке? (Р)

у меня есть фрейм данных из 9 столбцов, состоящий из инвентаризации факторов. В каждой строке могут быть заполнены все 9 столбцов (как в этой строке содержится 9 "вещей"), но большинство из них (большинство из них между 3-4). Столбцы также не являются конкретными, например, если элемент 200 отображается в Столбцах 1 и 3, это одно и то же. Я хотел бы создать матрицу, которая является двоичной для каждой строки, которая включает все факторы.

Ex (сокращено до 4 столбцов, чтобы получить точку)

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

должны включить в

     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

Я просмотрел writeBin / readBin, K-кластеризацию (что я хотел бы сделать, но сначала мне нужно избавиться от NAs), нечеткую кластеризацию, кластеризацию тегов. Просто не знаю, в каком направлении идти.

Я попытался написать два цикла, которые вытягивают данные из Матрицы по столбцу / строке, а затем сохраняют 0 и 1 соответственно в новой матрице, но я думаю, что были проблемы с областью.

Вы самые лучшие. Спасибо!

3 ответов


вот базовое решение 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

Это должно сделать трюк:

# 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)

результат:

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

Это все отличные ответы. Думал, что я внесу оригинальное решение, которое я написал, что мой друг модифицирован, чтобы действительно работать.

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

два для циклов работает после установки некоторых более ранних параметров, но это невероятно медленно. Похоже, другие решения работают намного быстрее!