我有一个具有以下结构的数据框
test <- data.frame(col = c('a; ff; cc; rr;', 'rr; a; cc; e;'))
现在我想从中创建一个数据框,其中包含测试数据框中每个唯一值的命名列。唯一值是以';'结尾的值角色,从空间开始,不包括空间。然后对于列中的每一行,我希望用1或0填充虚拟列。如下所示
data.frame(a = c(1,1), ff = c(1,0), cc = c(1,1), rr = c(1,0), e = c(0,1))
a ff cc rr e
1 1 1 1 1 0
2 1 0 1 1 1
我尝试使用for循环和列中的唯一值创建一个df,但它变得很乱。我有一个可用的向量,包含列的唯一值。问题是如何创建1和0。我在mutate_all()
尝试了一些grep()
函数,但这不起作用。
答案 0 :(得分:8)
我会使用splitstackshape
mtabulate
来自qdapTools
个套餐,将其作为一个班轮,
即。
library(splitstackshape)
library(qdapTools)
mtabulate(as.data.frame(t(cSplit(test, 'col', sep = ';', 'wide'))))
# a cc ff rr e
#V1 1 1 1 1 0
#V2 1 1 0 1 1
它也可以是splitstackshape
,因为@ A5C1D2H2I1M1N2O1R2T1在评论中提及,
cSplit_e(test, "col", ";", mode = "binary", type = "character", fill = 0)
答案 1 :(得分:6)
这是一个可能的data.table
实现。首先,我们将行拆分成列,融化成一列并将其展开,同时计算每行的事件
library(data.table)
test2 <- setDT(test)[, tstrsplit(col, "; |;")]
dcast(melt(test2, measure = names(test2)), rowid(variable) ~ value, length)
# variable a cc e ff rr
# 1: 1 1 1 0 1 1
# 2: 2 1 1 1 0 1
答案 2 :(得分:3)
我们可以使用tidyverse
library(tidyverse)
rownames_to_column(test, 'grp') %>%
separate_rows(col) %>%
filter(col!="") %>%
count( grp, col) %>%
spread(col, n, fill = 0) %>%
ungroup() %>%
select(-grp)
# A tibble: 2 × 5
# a cc e ff rr
#* <dbl> <dbl> <dbl> <dbl> <dbl>
#1 1 1 0 1 1
#2 1 1 1 0 1
答案 3 :(得分:3)
这是基础R解决方案。首先删除空间。获得所有独特的组合。拆分实际数据框,然后在cols中检查它的存在,这将包含所有组合。然后你得到一个逻辑矩阵,可以很容易地转换成数字。
test=as.data.frame(apply(test,2,function(x)gsub('\\s+', '',x)))
cols=unique(unlist(strsplit(as.character(test$col), split = ';')))
yy=strsplit(as.character(test$col), split = ';')
z=as.data.frame(do.call.rbind(lapply(yy, function(x) cols %in% x)))
names(z)=cols
z=as.data.frame(lapply(z, as.integer))
答案 4 :(得分:3)
这是一个基础R方法:
x <- strsplit(as.character(test$col), ";\\s?") # split the strings
lvl <- unique(unlist(x)) # get unique elements
x <- lapply(x, factor, levels = lvl) # convert to factor
t(sapply(x, table)) # count elements and transpose
# a ff cc rr e
#[1,] 1 1 1 1 0
#[2,] 1 0 1 1 1
答案 5 :(得分:3)
tidytext
和tidyverse
library(tidyverse)
library(tidytext) #for unnest_tokens()
df <- test %>%
unnest_tokens(word, col) %>%
rownames_to_column(var="row") %>%
mutate(row = floor(parse_number(row)),
val = 1) %>%
spread(word, val, fill = 0) %>%
select(-row)
df
# a cc e ff rr
#1 1 1 0 1 1
#2 1 1 1 0 1
答案 6 :(得分:1)
另一个没有任何额外包的简单解决方案:
x = c('a; ff; cc; rr;', 'rr; a; cc; e;')
G = lapply(strsplit(x,';'), trimws)
dict = sort(unique(unlist(G)))
do.call(rbind, lapply(G, function(g) 1*sapply(dict, function(d) d %in% g)))