我有一个像这样的数据框
df <-data.frame(id = c(1,2),
value = c(25,24),
features = c("A,B,D,F","C,B,E"))
print(df)
id,value,features
1,25,"A,B,D,F"
2,24,"C,B,E"
我想重塑它:
id,value,A,B,C,D,E,F
1,25,1,1,0,1,0,1
2,24,0,1,1,0,1,0
我猜测第一步是识别df$features
列中的唯一值,但是一旦我有了这个列表,我就不确定什么是有效的(即矢量化)创建最终数据集的方法是。
这感觉就像是dplyr
或reshape2
的操作,但我不确定如何处理此问题。
答案 0 :(得分:3)
这是适当转换后merge
的另一个用例。
library(reshape2)
f<-with(df,stack(setNames(strsplit(as.character(features),","),id)))
d<-dcast(f,ind~values,length,value.var="ind")
out<-merge(df[,1:2],d,by.x="id",by.y="ind")
print(out)
id value A B C D E F 1 1 25 1 1 0 1 0 1 2 2 24 0 1 1 0 1 0
这也可以使用默认库(没有reshape2
)以各种稍微混乱的方式完成。在上文中,您可以使用以下内容替换d
和out
行:
d<-xtabs(count~ind+values,transform(f,count=1))
out<-merge(df[,1:2],as.data.frame.matrix(d),by.x="id",by.y="row.names")
答案 1 :(得分:2)
你可以这样做:
library(splitstackshape)
library(qdapTools)
df1 = data.frame(cSplit(df, 'features', sep=',', type.convert=F))
cbind(df1[1:2], mtabulate(as.data.frame(t(df1[-c(1,2)]))))
# id value A B C D E F
#1: 1 25 1 1 0 1 0 1
#2: 2 24 0 1 1 0 1 0
答案 2 :(得分:2)
使用splitstackshape
和data.table
的另一个人(安装说明here):
require(splitstackshape)
require(data.table) # v1.9.5+
ans <- cSplit(df, 'features', sep = ',', 'long')
dcast(ans, id + value ~ features, fun.aggregate = length)
# id value A B C D E F
# 1: 1 25 1 1 0 1 0 1
# 2: 2 24 0 1 1 0 1 0
如果您正在使用data.table v1.9.4
,请将dcast
替换为dcast.data.table
。
或者,您可以使用cSplit_e
,如下所示:
cSplit_e(df, "features", ",", type = "character", fill = 0)
## id value features features_A features_B features_C features_D features_E features_F
## 1 1 25 A,B,D,F 1 1 0 1 0 1
## 2 2 24 C,B,E 0 1 1 0 1 0
答案 3 :(得分:1)
dplyr / tidyr解决方案
library(dplyr)
library(tidyr)
separate(df,features,1:4,",",extra="merge") %>%
gather(key,letter,-id,-value) %>%
filter(!is.na(letter)) %>%
select(-key) %>%
mutate(n=1) %>%
spread(letter,n) %>%
mutate_each(funs(ifelse(is.na(.),0,1)),A:F)