按频率/值订购离散x标度


137

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

我尝试排序或排序,但导致对x轴进行排序,但没有分别对条进行排序。

我做错了什么?

Answers:


105

尝试在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()

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


197

对我来说,最好的方法是使用带有类别的vector,以便将其作为的limits参数scale_x_discrete。我认为这是非常简单直接的解决方案。

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

在此处输入图片说明


1
@HendyIrawan没有图例,除非您还有其他尺寸(颜色,填充)也映射到同一变量。
格雷戈尔·托马斯

5
我认为这是最好的答案。它控制x轴值的顺序,并且不会变换或影响数据框。使用factorreorder更改数据的特征(尽管在ggplot()调用中),对于眼前的问题,它所做的比其需要做的更多。
mjandrews

2
这应该是公认的答案!为什么要通过编写2到3行代码来使事情复杂化,而只需一行优雅(预定义)的代码行就可以做到这一点?
SilSur

1
这对我来说也可以按y的值订购x: scale_x_discrete(limits = DT$x[order(-DT$y)])+
armipunk

38

您可以使用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")

我希望它也有负高度,但事实并非如此,所以它可行!


5
我很惊讶这个答案没有更多的投票,90%的时候这是正确的方法。
Gregor Thomas

1
我认为这两个因素调用都是多余的。第一个参数有一个隐式调用factor,第二个参数被假定为数字。
IRTFM

一种有助于我弄清楚这些解决方案在做什么的解释:rstudio-pubs-static.s3.amazonaws.com/…–
keithpjolley

30

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()与一起使用fct_infreq()

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

在此处输入图片说明


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函数创建了另一个数据框,该数据框的新列名为same,但_o末尾有a 。此新列的级别按升序排列,因此ggplot2会自动按照该顺序进行绘制。

这在某种程度上是受限制的(仅适用于字符或因子以及列和升序的数字组合),但我仍然发现它对于随时随地进行绘制非常有用。


reorder直接使用相比,我想我看不出有什么好处。ggplot(df, aes(x = reorder(AXIS_X, COLUMN_Y), y = COLUMN_Y)) + ...简而言之,没有帮助程序功能,是否会做同样的事情?
格雷戈尔·托马斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.