简体   繁体   English

ggplot2 Facet Wrap按y轴重新排序,而不是x轴

[英]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. 请注意, audicyl值不是递增的顺序,表明我们的重新排序正常工作。

在此输入图像描述

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM