在使用stack='identity'
绘制堆积条形图时,我注意到每个条形图中堆栈的顺序是不同的,看似随机。这是使用stat='bin'
的图,也就是说,ggplot在绘图之前动态计算每个类别中的元素数(data.table
稍后会出现):
library(ggplot2)
library(data.table)
diamonds <- data.table(diamonds)
ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar(position="fill")
在每个栏中,“剪切”的顺序为&#39;遵循因子顺序。但是,如果我在绘图之前总结并使用stat=identity
,则此订单将丢失:
diamonds_sum <- diamonds[, list(.N), by=list(cut, clarity)]
ggplot(diamonds_sum, aes(clarity, y=N, fill = cut)) + geom_bar(stat="identity", position="fill")
尽管两个表中的级别顺序相同,但仍会发生这种情况:
levels(diamonds_sum$cut) == levels(diamonds$cut)
[1] TRUE TRUE TRUE TRUE TRUE
所以问题是2倍:(i)为什么堆栈的顺序不一样? (ii)如何解决这个问题?
简单的解决方案当然一直使用stat='bin'
,但是我的真实数据集有几个百万条目,总结然后绘图更快。
答案 0 :(得分:2)
原因是在汇总后,订单会在您的新 data.table 中混淆,而ggplot2
会将行的顺序作为输入。比较例如以下两种方法的输出(只显示前10行,因为它们说明差异足够好):
> diamonds[, .N, by=.(cut, clarity)]
cut clarity N
1: Ideal SI2 2598
2: Premium SI1 3575
3: Good VS1 648
4: Premium VS2 3357
5: Good SI2 1081
6: Very Good VVS2 1235
7: Very Good VVS1 789
8: Very Good SI1 3240
9: Fair VS2 261
10: Very Good VS1 1775
> diamonds[, .N, by=.(cut, clarity)][order(clarity,cut)]
cut clarity N
1: Fair I1 210
2: Good I1 96
3: Very Good I1 84
4: Premium I1 205
5: Ideal I1 146
6: Fair SI2 466
7: Good SI2 1081
8: Very Good SI2 2100
9: Premium SI2 2949
10: Ideal SI2 2598
正如您所看到的,您的原始代码会产生混合行,而第二种方法会产生订单行。所以,当你这样做时:
diamonds_sum <- diamonds[, .N, by=.(cut, clarity)][order(clarity,cut)]
然后用:
绘图ggplot(diamonds_sum, aes(clarity, y=N, fill = cut)) +
geom_bar(stat="identity", position="fill")
你得到了理想的结果:
同样dplyr
会给你相同的行为。然后,您需要arrange
才能获得正确的订单。比较以下两个的输出:
diamonds %>% group_by(cut, clarity) %>% tally()
diamonds %>% group_by(cut, clarity) %>% tally() %>% arrange(clarity,cut)
使用基数R汇总不会导致您描述的问题。当你这样做时:
diamonds_sum <- aggregate(diamonds[,"cut",with=FALSE], list(diamonds$cut,diamonds$clarity), length)
然后用:
绘图ggplot(diamonds_sum, aes(Group.2, y=cut, fill = Group.1)) +
geom_bar(stat="identity", position="fill")
你得到了正确的结果: