如何用reshape2/tidyr实现按id展开type与type_val的全组合列?
解决思路:生成type_val的笛卡尔积组合
我明白你的需求了——你要的不是常规的宽表转换,而是让每个id下t1的所有type_val和t2的所有type_val做全组合配对,同时带出各自对应的val。普通的spread只能把同组的type_val对应起来,没法生成这种跨组合的结果,所以得换个思路拆分再合并:
具体步骤(用dplyr实现)
- 先把原数据按
type拆分成t1和t2两个子集,并重命名列名方便后续识别; - 按
id对两个子集做交叉连接(也就是每个id下的t1行和t2行全配对); - 最后按需求排序整理列顺序。
完整代码示例
# 加载需要的包 library(dplyr) # 生成你的示例数据 df <- data.frame(id=rep(letters[1:2],6), type=c(rep('t1',6), rep('t2',6)), type_val=rep(c(1,1,2,2,3,3),2), val=1:12) # 拆分t1和t2数据并重命名列 t1_df <- df %>% filter(type == "t1") %>% rename(type_t1 = type_val, val_t1 = val) %>% select(id, type_t1, val_t1) t2_df <- df %>% filter(type == "t2") %>% rename(type_t2 = type_val, val_t2 = val) %>% select(id, type_t2, val_t2) # 按id做交叉连接,生成所有组合 result <- t1_df %>% inner_join(t2_df, by = "id") %>% arrange(id, type_t1, type_t2) %>% select(id, type_t1, type_t2, val_t1, val_t2) # 调整列顺序到你要的格式 # 查看结果 print(result)
为什么普通spread不行?
spread(df, type, val)会把每个id-type_val对应的t1和t2值放在同一行,比如id=a, type_val=1对应val_t1=1, val_t2=7,但它没法生成t1=1和t2=2、t1=2和t2=1这种跨type_val的组合——而我们用交叉连接正好解决了这个问题,让每个id下的t1和t2的type_val实现全配对。
内容的提问来源于stack exchange,提问作者user3375672
相关产品推荐
相关产品推荐

