如何使用stat =' identity'?

时间:2015-11-04 15:55:40

标签: r ggplot2

在使用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")

enter image description here

在每个栏中,“剪切”的顺序为&#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")

enter image description here

尽管两个表中的级别顺序相同,但仍会发生这种情况:

levels(diamonds_sum$cut) == levels(diamonds$cut)
[1] TRUE TRUE TRUE TRUE TRUE

所以问题是2倍:(i)为什么堆栈的顺序不一样? (ii)如何解决这个问题?

简单的解决方案当然一直使用stat='bin',但是我的真实数据集有几个百万条目,总结然后绘图更快。

1 个答案:

答案 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")

你得到了理想的结果:

enter image description here

同样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")

你得到了正确的结果:

enter image description here