[英]ggplot2 Facet Wrap Reorder by y-axis, Not x-axis
I want to plot faceted bar graphs and order them left-to-right from the largest to smallest values. 我想绘制多面条形图并从最大值到最小值从左到右排序。 I should be able to do this with code similar to this:
我应该能够使用类似于此的代码执行此操作:
library(ggplot2)
ggplot(mpg, aes(reorder(cyl, -hwy), hwy)) +
geom_col() +
facet_wrap(~ manufacturer, scales = "free")
Instead what I get is ordering by the x-axis which happens to be 'cyl', smallest to largest values. 相反,我得到的是x轴排序,恰好是'cyl',从最小值到最大值。 How do I order descending, by the y-axis, so it looks like a Pareto chart?
如何按y轴顺序下降,看起来像帕累托图? It has to be faceted as well.
它也必须是分面的。 Thank you.
谢谢。
If I understand your question, the goal is to plot the average highway mpg (the hwy
column) by cyl
for each manufacturer
. 如果我理解你的问题,我们的目标是绘制公路平均英里(该
hwy
列)由cyl
每个manufacturer
。 Within each manufacturer
, you want to order the x-axis (the cyl
values), by the mean hwy
value for each cyl
. 在每个
manufacturer
,您希望通过每个cyl
的平均hwy
值来订购x轴( cyl
值)。
To do that, we need to create the plots separately for each manufacturer and then lay them out together. 为此,我们需要为每个制造商单独创建绘图,然后将它们放在一起。 This is because we can't have different x-axis orderings (
cyl
orderings in this case) for different panels in the same plot. 这是因为对于同一图中的不同面板,我们不能有不同的x轴排序(在这种情况下为
cyl
排序)。 (UPDATE: I stand corrected. @missuse's answer links to functions written by David Robinson , based on a blog post by Tyler Rinker to vary the x-axis label order in facetted plots.) So, we'll create a list of plots and then lay them out together, as if they were facetted. (更新:我的观点得到纠正。@ missuse的答案链接到David Robinson编写的函数 ,基于Tyler Rinker的博客文章,改变了刻面图中的x轴标签顺序。)因此,我们将创建一个图表列表和然后把它们放在一起,好像它们被刻面了一样。
library(tidyverse)
library(egg)
Since in the real data, the mean value of hwy
is always monotonically decreasing with increasing cyl
, we'll create an artificially high hwy
value for 8-cylinder Audis, just for illustration: 因为在实际数据中,
hwy
的平均值总是随着cyl
增加而单调递减,我们将为8缸Audis创建一个人为的高hwy
值,仅用于说明:
mpg$hwy[mpg$manufacturer=="audi" & mpg$cyl==8] = 40
Now we split the data by manufacturer
so we can create a separate plot, and therefore a separate cyl
ordering for each manufacturer. 现在我们按
manufacturer
分割数据,这样我们就可以创建一个单独的图,因此每个制造商都有一个单独的cyl
排序。 We'll use the map
function to iterate over the manufacturers. 我们将使用
map
函数迭代制造商。
plot.list = split(mpg, mpg$manufacturer) %>%
map(function(dat) {
# Order cyl by mean(hwy)
dat = dat %>% group_by(manufacturer, cyl) %>%
summarise(hwy = mean(hwy)) %>%
arrange(desc(hwy)) %>%
mutate(cyl = factor(cyl, levels=cyl))
ggplot(dat, aes(cyl, hwy)) +
geom_col() +
facet_wrap(~ manufacturer) +
theme(axis.title=element_blank()) +
expand_limits(y=mpg %>%
group_by(manufacturer,cyl) %>%
mutate(hwy=mean(hwy)) %>%
pull(hwy) %>% max)
})
Now let's remove the y-axis values and ticks from the plot that won't be in the first column when we lay out the plots together: 现在让我们从绘图中删除y轴值和刻度,当我们将这些绘图放在一起时,这些值将不在第一列中:
num_cols = 5
plot.list[-seq(1,length(plot.list), num_cols)] =
lapply(plot.list[-seq(1,length(plot.list), num_cols)], function(p) {
p + theme(axis.text.y=element_blank(),
axis.ticks.y=element_blank())
})
Finally, we lay out the plots. 最后,我们列出了这些情节。
ggarrange
from the egg
package ensures that the panels all have the same width (otherwise the panels in the first column would be narrower than the others, due to space taken up by the y-axis labels). 来自
egg
包装的ggarrange
确保面板都具有相同的宽度(否则由于y轴标签占据的空间,第一列中的面板将比其他面板更窄)。
ggarrange(plots=plot.list, left="Highway MPG", bottom="Cylinders", ncol=num_cols)
Note that the cyl
values for audi
are not in increasing order, showing that our reordering worked properly. 请注意,
audi
的cyl
值不是递增的顺序,表明我们的重新排序正常工作。
Here is a different approach that can be performed directly in ggplot utilizing two functions from here . 这是一种不同的方法,可以使用这里的两个函数直接在ggplot中执行。 I will use eipi10's example:
我将使用eipi10的例子:
library(tidyverse)
mpg$hwy[mpg$manufacturer=="audi" & mpg$cyl==8] <- 40
dat <- mpg %>% group_by(manufacturer, cyl) %>%
summarise(hwy = mean(hwy)) %>%
arrange(desc(hwy)) %>%
mutate(cyl = factor(cyl, levels = cyl))
Functions: 功能:
reorder_within <- function(x, by, within, fun = mean, sep = "___", ...) {
new_x <- paste(x, within, sep = sep)
stats::reorder(new_x, by, FUN = fun)
}
scale_x_reordered <- function(..., sep = "___") {
reg <- paste0(sep, ".+$")
ggplot2::scale_x_discrete(labels = function(x) gsub(reg, "", x), ...)
}
plot: 情节:
ggplot(dat, aes(reorder_within(cyl, -hwy, manufacturer), y = hwy), hwy) +
geom_col() +
scale_x_reordered() +
facet_wrap(~ manufacturer, scales = "free") +
theme(axis.title=element_blank())
for ascending order you would: reorder_within(cyl, hwy, manufacturer)
对于升序,你会:
reorder_within(cyl, hwy, manufacturer)
Plot without the functions: 没有功能的情节:
ggplot(dat, aes(cyl, y = hwy)) +
geom_col() +
facet_wrap(~ manufacturer, scales = "free") +
theme(axis.title=element_blank())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.