【发布时间】:2014-10-24 23:53:42
【问题描述】:
我有:
id choice
----------
1 "a,b,c"
2 "c"
3 "a,c"
4 "b,c"
我需要
id a b c
---------
1 1 1 1
2 0 0 1
3 0 0 1
4 0 1 1
(或等效的 TRUE/FALSE 值)
有没有办法在 R 中做到这一点?我已经查看了strsplit,但这似乎没有帮助。
【问题讨论】:
标签: r
我有:
id choice
----------
1 "a,b,c"
2 "c"
3 "a,c"
4 "b,c"
我需要
id a b c
---------
1 1 1 1
2 0 0 1
3 0 0 1
4 0 1 1
(或等效的 TRUE/FALSE 值)
有没有办法在 R 中做到这一点?我已经查看了strsplit,但这似乎没有帮助。
【问题讨论】:
标签: r
这正是我的“splitstackshape”包中的cSplit_e 的设计目的。
library(splitstackshape)
cSplit_e(DF, "choice", sep = ",", mode = "binary",
type = "character", fill = 0, drop = TRUE)
# id choice_a choice_b choice_c
# 1 1 1 1 1
# 2 2 0 0 1
# 3 3 1 0 1
# 4 4 0 1 1
这使用来自@G.Grothendieck 的答案的DF 作为输入:
Lines <- 'id choice
----------
1 "a,b,c"
2 "c"
3 "a,c"
4 "b,c"'
DF <- read.table(text = Lines, header = TRUE, comment = "-", as.is = TRUE)
【讨论】:
cSpit 是一个非常好的函数系列,非常适合整理讨厌的数据类型。干得好+1
试试这个:
txt = 'id choice
----------
1 "a,b,c"
2 "c"
3 "a,c"
4 "b,c"'
library(dplyr)
txt %>% textConnection %>%
read.table(skip = 2, stringsAsFactors = FALSE) %>%
select(V2) %>% unlist %>%
strsplit("[,]") %>%
lapply(function(x) data.frame(t(table(c(x, "a", "b", "c"))>1))) %>%
rbind_all
然后你会得到
Source: local data frame [4 x 3]
a b c
1 TRUE TRUE TRUE
2 FALSE FALSE TRUE
3 TRUE FALSE TRUE
4 FALSE TRUE TRUE
【讨论】:
这假设像 @kohske 所做的那样,您的数据实际上看起来就像您提供的那样。如果没有请以后使用dput分享数据:
txt = 'id choice
----------
1 "a,b,c"
2 "c"
3 "a,c"
4 "b,c"'
dat <- setNames(read.table(text=txt, skip = 2, stringsAsFactors = FALSE),
strsplit(strsplit(txt, "\n")[[1]][1], "\\s+")[[1]]
)
library(qdapTools)
matrix2df(mtabulate(unlist(lapply(split(dat[[2]], dat[[1]]),
strsplit, ",\\s*"), recursive=FALSE)), "id")
我讨厌嵌套调用,因为我熟悉了magrittr 的管道 %>% 所以这里使用的是管道:
library(magrittr)
txt %>% read.table(text=., skip = 2, stringsAsFactors = FALSE) %>%
setNames(strsplit(strsplit(txt, "\n")[[1]][1], "\\s+")[[1]]) %>%
with(split(choice, id)) %>%
lapply(strsplit, ",\\s*") %>%
unlist(recursive=FALSE) %>%
mtabulate %>%
matrix2df("id")
## id a b c
## 1 1 1 1 1
## 2 2 0 0 1
## 3 3 1 0 1
## 4 4 0 1 1
【讨论】:
使用strsplit 拆分choice 创建s 并将DF$id 作为名称。从s 提取所有级别的向量all_lev。然后sapply 是s 之上的一个函数,它从s 的每个组件创建一个因子并在其上运行table。最后转置。
s <- setNames( strsplit(DF$choice, ","), DF$id )
all_lev <- sort(unique(unlist(s)))
m <- t(sapply(s, function(x) table(factor(x, lev = all_lev))))
这给出了以下矩阵,其中行名是 id:
> m
a b c
1 1 1 1
2 0 0 1
3 1 0 1
4 0 1 1
如果您更喜欢数据框,请使用上面的m:
data.frame(id = rownames(m), m)
注意 1:如果我们知道级别总是"a"、"b" 和"c",那么我们可以将all_lev硬编码为:
s <- setNames( strsplit(DF$choice, ","), DF$id )
m <- t(sapply(s, function(x) table(factor(x, lev = c("a", "b", "c")))))
注意 2:我们假设 DF 是这样的:
Lines <- 'id choice
----------
1 "a,b,c"
2 "c"
3 "a,c"
4 "b,c"'
DF <- read.table(text = Lines, header = TRUE, comment = "-", as.is = TRUE)
更新缩短答案。
【讨论】: