2012-01-24 12 views
6

Mam ramkę danych z 9 kolumn składającą się z inwentaryzacji czynników. Każdy rząd może mieć wypełnione wszystkie 9 kolumn (jak w tym wierszu zawiera 9 "rzeczy"), ale większość nie ma (większość ma od 3-4). Kolumny też nie są specyficzne, tak jak w przypadku, gdy pozycja 200 pojawia się w kolumnach 1 i 3, to jest to samo. Chciałbym utworzyć macierz, która jest binarna dla każdego wiersza, który zawiera wszystkie czynniki.Jak utworzyć binarną macierz ekwipunku na wiersz? (R)

Ex (skrócony do 4 kolumn tak aby uzyskać punkt w poprzek)

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

powinien przekształcić

 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 

Przyjrzeliśmy się writeBin/readBin K-klastrów (co jest coś chciałbym, ale najpierw muszę pozbyć się NA), klastrowania rozmytego, grupowania tagów. Po prostu trochę zagubiony w jakim kierunku pójść.

Próbowałem napisać dwa dla pętli, które pobierają dane z macierzy przez kolumnę/wiersz, a następnie zapisać odpowiednio 0 i 1 w nowej macierzy, ale myślę, że były problemy z zasięgiem.

Jesteście najlepsi. Dzięki!

Odpowiedz

5

Oto rozwiązanie baza 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 Ten kawałek cindla dmucha w moim umyśle. –

+0

Josh, to robi wrażenie. Czy istnieje termin na to, co się nazywa? Myślałem o matrycy inwentarzowej, macierzy przedmiotów lub macierzy binarnej, ale wszystkie one wydają się odnosić do innych pomysłów. –

+0

Dzięki. W moim rodzaju * myślę o * wyniku jako matrycy wskaźnikowej (po funkcji [wskaźnikowej] (http://en.wikipedia.org/wiki/Indicator_function)) macierzy obecności/nieobecności (ponieważ koduje ona czy nie każdy przedmiot jest obecny lub nieobecny w danym wierszu). Nie jestem pewien, czy istnieje akceptowalna nazwa ogólna. –

3

To powinno załatwić sprawę:

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

Rezultat:

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

Są to wielkie odpowiedzi. Pomyślałem, że przyczynię się do oryginalnego rozwiązania, które napisałem, że mój przyjaciel zmodyfikował się tak, aby faktycznie działał.

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

Dwa dla pętli działa po ustawieniu niektórych wcześniejszych parametrów, ale jest niesamowicie powolny. Wygląda na to, że te inne rozwiązania działają znacznie szybciej!