例如,我有一个如下所示的数据框:
df = data.frame(x=c('a, b, c','b, c', 'd, e'))
理想情况下,我最终会得到一个如下所示的数据框:
df.transformed = data.frame(x.a = c(1,0,0),
x.b = c(1,1,0),
x.c = c(1,1,0),
x.d = c(0,0,1),
x.e = c(0,0,1))
x
中每个可能的逗号分隔值已分开。
我已经多次为这个问题编写了手动解决方案,但这是我在调查数据中经常遇到的问题让我想知道为什么这个问题没有包含在像tidyr
这样的包中,因为{该包中的{1}}函数似乎不太有用。我希望能够在加载必要的软件包后在一行中完成此操作。
答案 0 :(得分:2)
添加行号列,将x
分隔为行,并在x
中使用x.
为每个元素添加前缀。然后运行table
并将其转换为数据框。如果您不需要在每个名称前加上,则可以省略paste
行,如果您不需要数据框(表格可以),则可以省略最后一行。
library(dplyr)
library(tidyr)
df %>%
mutate(row = 1:n()) %>%
separate_rows(x) %>%
mutate(x = paste("x", x, sep = ".")) %>%
table %>%
as.data.frame.matrix
,并提供:
x.a x.b x.c x.d x.e
1 1 1 1 0 0
2 0 1 1 0 0
3 0 0 0 1 1
请注意,如果我们省略了可选行,那么我们就有了这个:
df %>%
mutate(row = 1:n()) %>%
separate_rows(x) %>%
table
,并提供:
x
row a b c d e
1 1 1 1 0 0
2 0 1 1 0 0
3 0 0 0 1 1
答案 1 :(得分:2)
这可以通过qdapTools
完成,我们将{x'除以,
后跟零或更多空格并使用mtabulate
library(qdapTools)
mtabulate(strsplit(as.character(df$x), ",\\s*"))
# a b c d e
#1 1 1 1 0 0
#2 0 1 1 0 0
#3 0 0 0 1 1
或者我们使用tidyverse
方法
library(tidyverse)
rownames_to_column(df, 'rn') %>% #add row names
separate_rows(x) %>% #split the rows into long format
mutate(i = 1) %>% #create a column of 1s
spread(x, i, fill = 0) %>% #spread to wide format
select(-rn) %>% #remove unnecessary columns
rename_all(funs(paste0("x.", .))) #rename if needed
# x.a x.b x.c x.d x.e
#1 1 1 1 0 0
#2 0 1 1 0 0
#3 0 0 0 1 1
注意:只需将我的评论作为解决方案发布
或另一个选项来自base R
table
- 没有使用套餐
table(stack(setNames(strsplit(as.character(df$x), ",\\s*"), seq_len(nrow(df))))[2:1])
# values
#ind a b c d e
# 1 1 1 1 0 0
# 2 0 1 1 0 0
# 3 0 0 0 1 1