从长(与多个类别),以宽格式

时间:2019-02-02 13:26:19

标签: r

我有一个长格式的数据框,其中每一列都可以采用多个值(用逗号分隔):

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_longdataset_wide有什么优雅的方法吗?

2 个答案:

答案 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中的tablebase 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))