我有一个data.frame,其中的单元格包含一系列术语。
我希望为该列表中的每个术语生成一个新变量,表明该术语在该给定单元格中是否存在。
我在data.frame中有多个不同的这样的实例,并且不知道列表组成的修道院。
示例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 ...
答案 0 :(得分: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)
}
答案 1 :(得分:2)
以下是data.table
和reshape2
解决方案
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(列表值成为单个列
dcast(....)
使用columns
A ,...,
Z 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]
答案 2 :(得分: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