我有一个长格式的数据框,其中每一列都可以采用多个值(用逗号分隔):
dataset_long = data.frame(id=1:5, type=c("A", "A, B", "C, A", "C", "A"))
> dataset_long
id type
1 1 A
2 2 A, B
3 3 C, A
4 4 C
5 5 A
我想将其转换为宽格式,以用于回归分析:
dataset_wide = data.frame(id=1:5,
type_A = c(1,1,1,0,1),
type_B = c(0,1,0,0,0),
type_C = c(0,0,1,1,0))
> dataset_wide
id type_A type_B type_C
1 1 1 0 0
2 2 1 1 0
3 3 1 0 1
4 4 0 0 1
5 5 1 0 0
有某种方式类似于“一个热编码”,但每一行可以属于多个类别。
从dataset_long
到dataset_wide
有什么优雅的方法吗?
答案 0 :(得分:0)
这段代码将产生您在示例中显示的结果
library(tidyverse)
dataset_long = data.frame(id=1:5, type=c("A", "A, B", "C, A", "C", "A"))
dataset_wide <- dataset_long %>% mutate(type_A=ifelse(regexpr('A', type)>0, 1, 0),
type_B=ifelse(regexpr('B', type)>0, 1, 0),
type_C=ifelse(regexpr('C', type)>0, 1, 0))
dataset_wide
#> id type type_A type_B type_C
#> 1 1 A 1 0 0
#> 2 2 A, B 1 1 0
#> 3 3 C, A 1 0 1
#> 4 4 C 0 0 1
#> 5 5 A 1 0 0
由reprex package(v0.2.1)于2019-02-02创建
但是,这不是数据集的“长到宽”重排。您的原始数据集长和新数据集宽都每个ID都有一行。通常,当我们说“长”时,是指每个ID多行折叠为“宽”格式,每个ID一行。
大多数人会称其为简单地创建三个指示符(或虚拟变量),以指示原始文本字符串中存在A,B或C。
P.S。我对ifelse()和regexpr()> 0的使用几乎肯定不是创建这三个指标变量的最简洁的方法。这些只是功能我通常默认为我自己的代码。
答案 1 :(得分:0)
我们可以通过分光做到这一点与在separate_rows
,创建1S的列中的定界符的“类型”。并将其“传播”为“宽”格式
library(tidyverse)
dataset_long %>%
separate_rows(type) %>%
mutate(type = paste0('type_', type)) %>%
mutate(ind = 1) %>%
spread(type, ind, fill = 0)
# id type_A type_B type_C
#1 1 1 0 0
#2 2 1 1 0
#3 3 1 0 1
#4 4 0 0 1
#5 5 1 0 0
或者使用strsplit
中的table
和base R
table(stack(setNames(strsplit(as.character(dataset_long$type),
', '), dataset_long$id))[2:1])
或与mtabulate
library(qdapTools)
mtabulate(setNames(strsplit(as.character(dataset_long$type), ', '), dataset_long$id))