2017-02-22 80 views
3

我有一个数据帧结构如下Dummify字符列,并找到独特的价值

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给定它变得混乱。我有一个可用的矢量包含列的唯一值。问题是如何创建一个和零。我尝试mutate_all()函数与grep()但这不起作用。

+1

你应该有'rr'两次IIRC。 –

回答

5

这是一个可能的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 
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

这里做,这是一个基础R解。首先删除空间。获得所有独特的组合。拆分实际的数据帧,然后检查是否存在它将有所有组合的列。然后你得到一个逻辑矩阵,可以很容易地转换成数字。

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

tidytexttidyverse另一种方法

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 
8

我会使用splitstackshapemtabulateqdapTools包得到这个作为一个衬垫, 即

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

不错的一个班轮。 –

+1

实际的1-liner将是'cSplit_e(test,“col”,“;”,mode =“binary”,type =“character”,fill = 0)':-) – A5C1D2H2I1M1N2O1R2T1

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