ggplot2:创建有序组条形图 - (使用reorder)

3
我希望创建一个分组条形图并保持顺序。如果只有单列而不是分组条形图,则使用reorder函数很明显。但不确定如何在融合的数据框上使用它。
以下是详细的代码示例说明:
假设我们有以下数据框:
d.nfl <- data.frame(Team1=c("Vikings", "Chicago", "GreenBay", "Detroit"), Win=c(20, 13, 9, 12))

绘制一个简单的条形图并翻转它。
ggplot(d.nfl, aes(x = Team1, y=Win)) + geom_bar(aes(fill=Team1), stat="identity") + coord_flip()

上述图表没有任何顺序,如果我想按胜利次数对图表进行排序,可以执行以下操作:

d.nfl$orderedTeam <- reorder(d.nfl$Team1, d.nfl$Win)
ggplot(d.nfl, aes(x = orderedTeam, y=Win)) + geom_bar(aes(fill=orderedTeam), stat="identity") + coord_flip()

现在假设我们向原始数据框添加另一列。
d.nfl$points <- c(12, 3, 45, 5)

     Team1 Win points
1  Vikings  20     12
2  Chicago  13      3
3 GreenBay   9     45
4  Detroit  12      5

要生成分组条形图,首先需要对其进行融合:

library(reshape2)
> d.nfl.melt <- melt(d.nfl[,c('Team1','Win','points')],id.vars = 1)
> ggplot(d.nfl.melt,aes(x = Team1,y = value)) + geom_bar(aes(fill = variable),position = "dodge", stat="identity") + coord_flip()

enter image description here

上面的 ggplot 是无序的。

但是我该如何制作按照顺序排列的分组柱状图(升序)?


2
你第一次重新排列了因子水平,它起作用了。也许尝试在融合的数据框上设置因子水平顺序...? - joran
1
可能是Order Bars in ggplot2 bar graph的重复问题。 - alistaire
与此相关的内容在这里。使用堆叠时,您只需要在绘图之前对数据集进行排序,但对于闪避似乎不起作用。 - aosmith
我建议这样做的原因是因为当我尝试过后,它确实有效。 - joran
1
请重新检查您设置的层级顺序,它是错误的。 - joran
显示剩余2条评论
2个回答

4

这不是问题。

最简单的方法是不要在熔断时放弃你的有序团队:

d.nfl.melt <- melt(d.nfl,id.vars = c("Team1", "orderedTeam"))

另外,我们可以在融合后使用reorder,并且仅在计算排序时使用Win元素:

d.nfl.melt$ordered_after_melting = reorder(
    d.nfl.melt$Team1,
    X = d.nfl.melt$value * (d.nfl.melt$variable == "Win")
)

另一个想法是将原始有序列中的“levels”应用于融合的因子变量:
d.nfl.melt$copied_levels = factor(
    d.nfl.melt$Team1,
    levels = levels(d.nfl$orderedTeam)
)

三种方法得出了相同的结果。(我省略了coord_flips,因为它们对问题并没有任何影响,但你当然可以将它们加回来。)
gridExtra::grid.arrange(
    ggplot(d.nfl.melt,aes(x = orderedTeam, y = value)) + 
        geom_bar(aes(fill = variable),position = "dodge", stat="identity"),
    ggplot(d.nfl.melt,aes(x = ordered_after_melting, y = value)) + 
        geom_bar(aes(fill = variable),position = "dodge", stat="identity"),
    ggplot(d.nfl.melt,aes(x = copied_levels, y = value)) + 
        geom_bar(aes(fill = variable),position = "dodge", stat="identity")
)

关于最简单的方法,我建议在融合时保留orderedTeam变量。您的代码似乎很难将其保留下来,但实际上很容易。

enter image description here


3
您的问题挑战在于如何基于融合列中的子集值重新排序因子 Team1。来自 @alistaire 和 @joran 的评论链接到了很好的答案。 简短的回答是,只需使用levels()将原始未融合的数据框的排序应用于新数据框即可。
library(reshape2)
#Picking up from your example code:
d.nfl.melt <- melt(d.nfl[,c('Team1','Win','points')],id.vars = 1)
levels(d.nfl.melt$Team1)
#Current order is alphabetical
#[1] "Chicago"  "Detroit"  "GreenBay" "Vikings" 

#Reorder based on Wins (using the same order from your earlier, unmelted data.frame)
d.nfl.melt$Team1 <- factor(d.nfl.melt$Team1, levels = levels(d.nfl$orderedTeam)) #SOLUTION
levels(d.nfl.melt$Team1)
#New order is ascending by wins
#[1] "GreenBay" "Detroit"  "Chicago"  "Vikings" 

ggplot(d.nfl.melt,aes(x = Team1,y = value)) + 
  geom_bar(aes(fill = variable),position = "dodge", stat="identity") + coord_flip()

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接