>我有一个这样的数据帧:
df <- data.frame(V1=c("a,b,c,d,e,f","a,b,c","e,f","b,d","a,e"))
我想根据varV1
中的类别生成所有可能的假人,如下所示:
df$a <- c(1,1,0,0,1)
df$b <- c(1,1,0,1,0)
df$c <- c(1,1,0,0,0)
df$d <- c(1,0,0,1,0)
df$e <- c(1,0,1,0,1)
df$f <- c(1,0,1,0,0)
> df
V1 a b c d e f
1 a,b,c,d,e,f 1 1 1 1 1 1
2 a,b,c 1 1 1 0 0 0
3 e,f 0 0 0 0 1 1
4 b,d 0 1 0 1 0 0
5 a,e 1 0 0 0 1 0
我怎样才能有效地做到这一点?我有一个大数据框,V1
有很多类别。
这是一个解决方案,它使用strsplit()
拆分字符串,dcast()
从长格式重塑为宽格式:
library(data.table)
setDT(df)[, rn := .I][
, strsplit(as.character(V1), ","), by = rn][
, dcast(.SD, rn ~ V1, length)]
rn a b c d e f 1: 1 1 1 1 1 1 1 2: 2 1 1 1 0 0 0 3: 3 0 0 0 0 1 1 4: 4 0 1 0 1 0 0 5: 5 1 0 0 0 1 0
如果要包含V1
,可以在之后加入:
library(data.table) # version 1.11.4 used
setDT(df)[, rn := .I][
, strsplit(as.character(V1), ","), by = rn][
, dcast(.SD, rn ~ V1, length)][
df, on = "rn"][
, setcolorder(.SD, "V1")]
V1 rn a b c d e f 1: a,b,c,d,e,f 1 1 1 1 1 1 1 2: a,b,c 2 1 1 1 0 0 0 3: e,f 3 0 0 0 0 1 1 4: b,d 4 0 1 0 1 0 0 5: a,e 5 1 0 0 0 1 0
setcolorder()
用于将V1
列移动到前面。
一个选项是使用splitstackshape::cSplit
拆分V1
列。确保使用drop = FALSE
以便保留V1
列。现在,使用tidyr::gather
转换为长格式,然后reshape2::dcast
将以宽格式转换数据。
library(tidyverse)
library(splitstackshape)
library(reshape2)
df %>% cSplit("V1", drop = FALSE, type.convert = FALSE) %>%
gather(key, value, -V1) %>%
filter(!is.na(value)) %>%
dcast(V1~value, fun.aggregate = length)
# V1 a b c d e f
# 1 a,b,c 1 1 1 0 0 0
# 2 a,b,c,d,e,f 1 1 1 1 1 1
# 3 a,e 1 0 0 0 1 0
# 4 b,d 0 1 0 1 0 0
# 5 e,f 0 0 0 0 1 1
数据:
df <- data.frame(V1=c("a,b,c,d,e,f","a,b,c","e,f","b,d","a,e"), stringsAsFactors = FALSE)