使用spread处理重复标识符时生成含NA的稀疏矩阵问题
解决
spread()处理重复key时的报错与非预期NA结果问题 我明白你遇到的困扰了——当数据框里存在重复的key值时,直接用spread()要么抛出重复标识符的错误,要么加上全局id后得到满是NA的对角矩阵,完全不是你想要的合并效果。
先重现你的测试数据方便大家理解:
library(tidyverse) dftest <- structure(list(key = c("a", "b", "c", "d", "c"), value = c(1, 2, 3, 2, 4)), .Names = c("key", "value"), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"))
问题根源
spread()的核心要求是每一行与key的组合必须唯一:
- 直接运行
dftest %>% spread(key, value)报错,就是因为key="c"对应了第3和第5行两个值,违反了唯一性要求; - 你添加全局
id列后,每一行都变成了唯一的个体,所以每个key只会在自己的行有值,其他行自然填充NA,就得到了对角矩阵。
解决方案:给重复key添加组内序号
我们需要给每个key的重复项分配一个组内的序号,让(组内序号, key)的组合变成唯一,这样spread后就能把同序号的行合并,得到你想要的结果:
dftest %>% group_by(key) %>% mutate(row_id = row_number()) %>% # 给每个key的重复项编组内序号 ungroup() %>% spread(key, value) %>% select(-row_id) # 移除辅助用的row_id列
运行后得到的结果正好符合你的预期:
# A tibble: 2 x 4 a b c d <dbl> <dbl> <dbl> <dbl> 1 1 2 3 2 2 NA NA 4 NA
原理说明
group_by(key) %>% mutate(row_id = row_number())会给每个key的第n次出现分配序号:唯一的a、b、d序号都是1,重复的c则分别是1和2;- 当执行
spread()时,相同row_id的行会被合并到同一行,所以row_id=1的行包含所有key的第一次取值,row_id=2的行只包含c的第二次取值,其他列自动填充NA,完美匹配你想要的输出。
如果之后你想把重复的key值合并成列表(比如c列显示c(3,4)),也可以用这个方式:
dftest %>% group_by(key) %>% summarise(value = list(value)) %>% spread(key, value)
内容的提问来源于stack exchange,提问作者Pancho Mulongeni
相关产品推荐
相关产品推荐

