【问题标题】:arranging order of stacked geom_bar in ggplot2ggplot2中堆叠geom_bar的排列顺序
【发布时间】:2026-02-13 19:15:01
【问题描述】:

我正在使用facet_wrapcoord_polar 绘制一些饼图,假设我有序列为ABC.D 的因子,用于x 轴,并使用facet_wrap(比如 3 个图表)和 coord_polar。我将有 3 个馅饼(馅饼 X,Y,Z),按顺时针方向排列为 A,B,C.D

当我想为每个方面单独重新排列因子的level 时出现问题,例如:

   A  B  C  D
X 10 20 30 40
Y 20 30 40 10
Z 30 40 10 20

我想要:

饼图 X 顺时针排列为:A,B,C.D

饼图 Y 顺时针排列为:D,A,B.C

饼图Z顺时针排列为:C,D,A.B

我可以在 ggplot2 中这样做吗?谢谢。

【问题讨论】:

  • 我认为你最好分别绘制 3 个图,并使用一些网格函数将图排列在单个设备上,以将图推送到视口上。 ggplot 希望数据以连贯的块形式出现,并且排除了在内部动态更改不同面板的因子顺序。如果您对网格视口的东西感兴趣,我可以按照这些思路提供答案吗?

标签: r ggplot2


【解决方案1】:

网格/视口方法可以像这样工作。首先,我们安排一些数据以匹配您显示的内容。正如您在问题中指定的那样,我们会轮换 XYZ 中的每一个的因子水平

## Your data
dat <- data.frame(X = factor(rep(LETTERS[1:4], times = c(10,20,30,40)), 
                             levels = LETTERS[1:4]),
                  Y = factor(rep(LETTERS[1:4], times = c(20,30,40,10)),
                             levels = LETTERS[c(4,1:3)]),
                  Z = factor(rep(LETTERS[1:4], times = c(30,40,10,20)),
                             levels = LETTERS[c(3:4,1:2)]))

接下来我们生成单独的饼图,旋转相同的scale_fill_manual() 颜色,以我们旋转数据中的级别的相同顺序,dat(为讨厌的颜色道歉 - 如何获得第一个 n ggplot 会正常使用的颜色?):

p1 <- ggplot(dat, aes(x = factor(1), fill = factor(X))) + 
          geom_bar(width = 1) + coord_polar(theta = "y") +
          scale_fill_manual(value = c("red","green","yellow","blue"))
p2 <- ggplot(dat, aes(x = factor(1), fill = factor(Y))) + 
          geom_bar(width = 1) + coord_polar(theta = "y") +
          scale_fill_manual(value = c("red","green","yellow","blue")[c(4,1:3)])
p3 <- ggplot(dat, aes(x = factor(1), fill = factor(Z))) + 
          geom_bar(width = 1) + coord_polar(theta = "y") +
          scale_fill_manual(value = c("red","green","yellow","blue")[c(3:4,1:2)])

现在我们需要一个新的绘图页面并在其上推送一个 2x2 布局:

grid.newpage()
pushViewport(viewport(layout = grid.layout(2,2)))

自定义函数允许我们为每个后续绘图简化设置行/列:

vplayout <- function(x, y) {
    viewport(layout.pos.row = x, layout.pos.col = y)
}

接下来,我们只需在正确的视口上绘制每个保存的 ggplot 对象,由参数 vp 指定:

print(p1, vp = vplayout(1,1))
print(p2, vp = vplayout(1,2))
print(p3, vp = vplayout(2,1))

上面的网格代码取自 Hadley 关于 ggplot 的优秀书籍的第 94 页。

这会产生:

【讨论】:

    最近更新 更多