如何用R的dcast/spread一次性将两列分类变量转宽表?
解决方法:一步实现长转宽(分两种常用方式)
先构造示例数据方便演示:
# 示例数据框 dat <- data.frame( bm = c(1,1,2,2), at4 = c("a","a","b","b"), n1 = c(10,20,30,40), cat = c("x","y","x","z"), clas = c("k","l","k","l") )
你的需求是把cat(x/y/z)和clas(k/l)的所有取值单独作为列,匹配行填1、否则填0,不需要生成cat+clas的组合列。可以通过先把两个分类变量堆叠成统一的长格式,再转宽来一步完成,以下是两种实现方式:
方式1:用reshape2的dcast
先通过melt把cat和clas合并成一个变量,再用dcast转宽:
library(reshape2) # 堆叠分类变量 + 生成标记列 + 转宽 result <- dcast( melt(dat, id.vars = c("bm", "at4", "n1"), measure.vars = c("cat", "clas"), variable.name = "type", value.name = "category") %>% mutate(temp1 = 1), bm + at4 + n1 ~ category, value.var = "temp1", fun.aggregate = sum, fill = 0 )
方式2:用tidyr的pivot_wider(tidyverse生态更推荐)
用pivot_longer堆叠变量,再用pivot_wider转宽,链式操作更直观:
library(tidyr) library(dplyr) result <- dat %>% # 把cat和clas堆叠成统一的category列 pivot_longer(cols = c(cat, clas), names_to = "type", values_to = "category") %>% # 生成匹配标记列 mutate(temp1 = 1) %>% # 转宽,按bm/at4/n1分组,category值作为列,不匹配填充0 pivot_wider( id_cols = c(bm, at4, n1), names_from = category, values_from = temp1, values_fill = 0, values_fn = list(temp1 = sum) )
两种方法得到的结果一致,都会生成包含x/y/z/k/l列的数据框,匹配行填1,不匹配填0,无需分步调用转宽函数。
内容的提问来源于stack exchange,提问作者Korpo
相关产品推荐
相关产品推荐

