2012-11-12 24 views
3

我有一個data.frame,其中的單元格包含一個術語列表。從數據框中嵌入的列表中獲取虛擬(T/F)變量

我希望爲該列表中找到的每個術語產生一個新變量,表明該術語在該給定單元格中是否存在。

我有一個data.frame中有多個不同的這種實例,並不知道列表的組成的priory。

一個例子data.frame

require(plyr) 

example<-data.frame(groups=letters) 

example<-adply(example, 
       1, 
       function(x) data.frame(value=t(list(sample(LETTERS, 4))))) 

    groups  value 
1  a F, Y, N, X 
2  b N, D, B, Y 
3  c W, J, S, U 
4  d I, S, N, A 
5  e S, Z, Y, A 
6  f O, R, J, A 

由此,我希望獲得

group  F  N  ... 
1  A TRUE TRUE ... 
2  B FALSE TRUE ... 
3  C FALSE FALSE ... 

回答

3

按照您的要求,在這裏它是在函數形式

myMatrix <- checkValues(example, makeMatrix=TRUE) 
myMatrix 

#  A  B  C  D  E  F ... 
# a FALSE FALSE FALSE FALSE FALSE FALSE ... 
# b FALSE FALSE FALSE FALSE FALSE TRUE ... 
# c FALSE FALSE FALSE TRUE FALSE FALSE ... 
# d FALSE TRUE FALSE TRUE FALSE FALSE ... 
# e TRUE FALSE FALSE FALSE FALSE FALSE ... 
# . 
# . 
# . 


功能

checkValues <- function(myDF, makeMatrix=FALSE, makeUnique=TRUE, sort=TRUE) { 
    # myDF should be a data frame containing columns `group` and `value` 
    # if `makeMatrix` is T, will convert the list into a long matrix 
    # `makeUnique` and `sort` only apply if `makeMatrix` is TRUE 
    # (otherwise, they are ignored) 

    res<- 
    lapply(myDF$value, function(L1) 
     t(sapply(myDF$value, function(L2) L1 %in% L2)) 
) 

    # Make the names purtty 
    names(res) <- myDF$group 

    for (i in 1:length(res)) 
     dimnames(res[[i]]) <- list(myDF$group, myDF$value[[i]]) 

    # convert the list to matrix 
    if (makeMatrix) { 
    res <- do.call(cbind, res) 

    # remove duplicates, if required 
    if (makeUnique) 
     res <- res[, !duplicated(res, MARGIN=2)] 

    # order columns, if required 
    if (sort) 
     res <- res[, order(colnames(res))] 
    } 

    return(res) 
} 
+0

好一個列表中應用此功能的所有唯一值的函數。 (g) –

+0

不,這只是你的第一個答案有一個小的錯字,其中函數(t)g%in%V'實際上應該是函數(g)g %以%V'表示。我對這個混亂感到抱歉。其他的困惑是,我不是問題的主人:) –

2

這裏是一個data.tablereshape2溶液

library(data.table) 
EX <- data.table(example) 

data.table(dcast(EX[,list(value = unlist(value)),by=groups], groups~value))[,lapply(.SD, is.na),by = groups] 

說明的步驟

  • EX[,list(value = unlist(value)),by=groups]創建在長格式data.table(LIS噸值成爲一個單一的式柱

  • dcast(....)轉換爲寬格式columns,...,Žbut is an ugly mess of NA`值

  • data.table()[,lapply(.SD), by = groups]經過所有列由基和羽爲邏輯值。 by不是必需的(並且會使其稍微慢一點),但是您必須以不同的方式處理組列,並且我不會受到困擾。


如果你知道速效元素事先

如果你知道什麼是列名事前,那麼這是一個簡單的替代使用dcast

很明顯,你會替換爲LETTERS可能值的向量。

EX[, setNames(as.list(LETTERS%in% unlist(value)), LETTERS),by = groups] 
1

感謝這裏的輸入,我還創建了一個require(plyr)解決方案。

比這兩種解決方案都不夠優雅,但由於某些原因,我仍然發現閱讀plyr解決方案很容易。

開發出能夠產生單一的虛擬變量

single.value.to.dummy<-function(value.name, list.of.lists){ 
    ldply(.data=list.of.lists, 
     function(list.element){ dummy<-value.name %in% list.element 
           names(dummy)<-value.name 
           return(dummy) 
     })} 

在列表

list.of.lists.to.dummy<-function(list.of.lists){ 

#Extract unique values 
    value.names<-unique(unlist(list.of.lists)) 

    dummy.frame<-llply(.data=value.names, 
         function(value.name){ 
         dummy<-single.value.to.dummy(value.name, list.of.lists) 
         return(dummy)}) 

    return(data.frame(dummy.frame)) 
} 

example<-cbind(example, list.of.lists.to.dummy(example$value)) 


groups  value  T  S  P  O  U  A  C  B  N  V  D  H  Y  F 
1  a T, S, P, O TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
2  b U, A, C, B FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE 
3  c S, N, V, D FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE 
4  d H, Y, F, X FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE 
5  e M, Y, O, X FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE 
6  f Y, A, K, S FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE