149

我正在使用具有离散 x 刻度的 ggplot 制作一个闪避的条形图,x 轴现在按字母顺序排列,但我需要重新排列它,以便它按 y 轴的值排序(即,最高的条形图将位于左侧)。

我尝试了排序或排序,但结果是对 x 轴进行排序,而不是分别对条形进行排序。

我做错了什么?

4

7 回答 7

208

对我来说最好的方法是使用带有类别的向量,以便我需要limits作为scale_x_discrete. 我认为这是非常简单明了的解决方案。

ggplot(mtcars, aes(factor(cyl))) + 
  geom_bar() + 
  scale_x_discrete(limits=c(8,4,6))

在此处输入图像描述

于 2011-09-18T22:15:02.237 回答
110

尝试手动设置 x 轴上的因子水平。例如:

library(ggplot2)
# Automatic levels
ggplot(mtcars, aes(factor(cyl))) + geom_bar()    

自动确定因子水平的汽车数据集的 ggplot

# Manual levels
cyl_table <- table(mtcars$cyl)
cyl_levels <- names(cyl_table)[order(cyl_table)]
mtcars$cyl2 <- factor(mtcars$cyl, levels = cyl_levels)
# Just to be clear, the above line is no different than:
# mtcars$cyl2 <- factor(mtcars$cyl, levels = c("6","4","8"))
# You can manually set the levels in whatever order you please. 
ggplot(mtcars, aes(cyl2)) + geom_bar()

手动重新排序因子水平的汽车数据集的 ggplot

正如詹姆斯在他的回答中指出的那样,reorder是重新排序因子水平的惯用方式。

mtcars$cyl3 <- with(mtcars, reorder(cyl, cyl, function(x) -length(x)))
ggplot(mtcars, aes(cyl3)) + geom_bar()

使用 reorder 函数对因子水平进行重新排序的汽车数据集的 ggplot

于 2010-07-15T12:23:37.513 回答
42

您可以使用reorder

qplot(reorder(factor(cyl),factor(cyl),length),data=mtcars,geom="bar")

编辑:

要在左侧拥有最高的酒吧,您必须使用一些杂物:

qplot(reorder(factor(cyl),factor(cyl),function(x) length(x)*-1),
   data=mtcars,geom="bar")

我希望这也有负高度,但它没有,所以它有效!

于 2010-07-15T14:39:27.460 回答
37

Hadley 一直在开发一个名为forcats. 这个包使任务变得更加容易。fct_infreq()当你想通过一个因子的频率改变 x 轴的顺序时,你可以利用它。对于本文中的mtcars示例,您希望cyl按每个级别的频率重新排序级别。最常出现的级别停留在左侧。您需要的只是fct_infreq().

library(ggplot2)
library(forcats)

ggplot(mtcars, aes(fct_infreq(factor(cyl)))) +
geom_bar() +
labs(x = "cyl")

如果你想反过来,你可以使用fct_rev()with fct_infreq()

ggplot(mtcars, aes(fct_rev(fct_infreq(factor(cyl))))) +
geom_bar() +
labs(x = "cyl") 

在此处输入图像描述

于 2016-12-22T06:46:20.467 回答
2

我意识到这是旧的,但也许我创建的这个功能对那里的人有用:

order_axis<-function(data, axis, column)
{
  # for interactivity with ggplot2
  arguments <- as.list(match.call())
  col <- eval(arguments$column, data)
  ax <- eval(arguments$axis, data)

  # evaluated factors
  a<-reorder(with(data, ax), 
             with(data, col))

  #new_data
  df<-cbind.data.frame(data)
  # define new var
  within(df, 
         do.call("<-",list(paste0(as.character(arguments$axis),"_o"), a)))
}

现在,使用此功能,您可以使用 ggplot2 交互式绘图,如下所示:

ggplot(order_axis(df, AXIS_X, COLUMN_Y), 
       aes(x = AXIS_X_o, y = COLUMN_Y)) +
        geom_bar(stat = "identity")

可以看出,该函数创建了另一个数据框,其中包含一个名称相同但末尾order_axis带有 a 的新列。_o这个新列的级别按升序排列,因此 ggplot2 会自动按该顺序绘制。

这有点有限(仅适用于字符或因子以及列的数字组合并按升序排列),但我仍然发现它对于在旅途中绘图非常有用。

于 2015-10-08T23:00:21.663 回答
0

如果您事先知道要绘制的级别,@Yuriy Petrovskiy 的回答会很棒。如果您不这样做(例如,因为您不想绘制数据中不存在的级别),请考虑使用limit函数来指定顺序:

library(ggplot2)

my_order <- as.character(c(8,3,4,5,6))    # the `as.character` calls are only
ggplot(mtcars, aes(as.character(cyl))) +  # necessary for the OP's example
  geom_bar() +
  scale_x_discrete(limits = function(x) my_order[my_order %in% x])

从以下文档scale_x_discrete

limits
      以下之一:
      - 使用默认比例值的 NULL
      - 定义比例的可能值及其顺序的字符向量
      - 接受现有(自动)值并返回新值的函数

否则你的图表会像这样结束(可能更可取):

ggplot(mtcars, aes(as.character(cyl))) +
  geom_bar() +
  scale_x_discrete(limits = my_order)

于 2021-03-04T21:09:20.300 回答
0

fct_relevel另一种选择是使用from forcats(part of )手动设置沿 x 轴的顺序tidyverse。但是,对于按频率排列,@jazzurro 通过使用fct_infreq(也来自forcats)提供了最佳答案。

library(tidyverse)

ggplot(iris, aes(
  x = fct_relevel(Species, 'virginica', 'versicolor', 'setosa'),
  y = Petal.Width)) +
  geom_col() +
  xlab("Species") +
  ylab("Petal Width") +
  theme_bw()

输出

在此处输入图像描述

fct_relevel此外,在使用inside之前,变量需要是一个因素ggplot。因此,只需factor先应用于变量,然后使用fct_relevel.

ggplot(mtcars, aes(fct_relevel(factor(cyl), "6", "8", "4"))) +
  geom_bar() +
  labs(x = "cyl")

输出

在此处输入图像描述

于 2021-12-26T18:32:16.340 回答