按频率/值排序离散 x 比例

发布于 2024-09-10 03:51:16 字数 156 浏览 6 评论 0原文

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

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

我做错了什么?

I am making a dodged bar chart using ggplot with discrete x scale, the x axis are now arranged in alphabetical order, but I need to rearrange it so that it is ordered by the value of the y-axis (i.e., the tallest bar will be positioned on the left).

I tried order or sort, but result in sort the x-axis, but not the bars respectively.

What have I done wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

旧梦荧光笔 2024-09-17 03:51:16

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

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

在此处输入图像描述

The best way for me was using vector with categories in order I need as limits parameter to scale_x_discrete. I think it is pretty simple and straightforward solution.

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

enter image description here

终止放荡 2024-09-17 03:51:16

尝试手动设置 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

正如 James 在他的回答中指出的那样, reorder 是重新排序因子级别的惯用方法。

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

汽车数据集的 ggplot,其中使用重新排序函数重新排序了因子水平

Try manually setting the levels of the factor on the x-axis. For example:

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

ggplot of the cars dataset with factor levels automatically determined

# 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 of the cars dataset with factor levels reordered manually

As James pointed out in his answer, reorder is the idiomatic way of reordering factor levels.

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

ggplot of the cars dataset with factor levels reordered using the reorder function

萧瑟寒风 2024-09-17 03:51:16

您可以使用重新排序

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")

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

You can use reorder:

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

Edit:

To have the tallest bar at the left, you have to use a bit of a kludge:

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

I would expect this to also have negative heights, but it doesn't, so it works!

小女人ら 2024-09-17 03:51:16

Hadley 一直在开发一个名为 forcats 的软件包。这个包使任务变得更加容易。当您想要按因子的频率更改 x 轴的顺序时,可以利用 fct_infreq()。对于本文中的 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") 

输入图像描述这里

Hadley has been developing a package called forcats. This package makes the task so much easier. You can exploit fct_infreq() when you want to change the order of x-axis by the frequency of a factor. In the case of the mtcars example in this post, you want to reorder levels of cyl by the frequency of each level. The level which appears most frequently stays on the left side. All you need is the fct_infreq().

library(ggplot2)
library(forcats)

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

If you wanna go the other way around, you can use fct_rev() along with fct_infreq().

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

enter image description here

○闲身 2024-09-17 03:51:16

我意识到这已经很旧了,但也许我创建的这个函数对那里的人有用:

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 函数创建另一个数据框,其中有一个名称相同但末尾带有 _o 的新列。这个新列的级别按升序排列,因此 ggplot2 会自动按该顺序绘制。

这有些限制(仅适用于列的字符或因子和数字组合并按升序排列),但我仍然发现它对于动态绘图非常有用。

I realize this is old, but maybe this function I created is useful to someone out there:

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)))
}

Now, with this function you can interactively plot with ggplot2, like this:

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

As can be seen, the order_axis function creates another dataframe with a new column named the same but with a _oat the end. This new column has levels in ascending order, so ggplot2 automatically plots in that order.

This is somewhat limited (only works for character or factor and numeric combinations of columns and in ascending order) but I still find it very useful for plotting on the go.

向日葵 2024-09-17 03:51:16

另一种选择是使用 forcatstidyverse 的一部分)中的 fct_relevel 手动设置沿 x 轴的顺序。然而,对于按频率排列,@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()

输出

enter image description here

此外,在 ggplot 内使用 fct_relevel 之前,该变量需要是一个因子。因此,只需先将 factor 应用于变量,然后使用 fct_relevel

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

输出

enter图像描述在这里

Another option is to manually set the order along the x-axis using fct_relevel from forcats (part of tidyverse). However, for arranging by frequency, @jazzurro provides the best answer by using fct_infreq (also from 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()

Output

enter image description here

Further, the variable needs to be a factor before using fct_relevel inside ggplot. So, just apply factor to the variable first, then use fct_relevel.

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

Output

enter image description here

芸娘子的小脾气 2024-09-17 03:51:16

如果您事先知道要绘制的级别,@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) intersect(my_order, x))

来自 scale_x_discrete 的文档:

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

否则,您的图表最终会像这样(可能更好):

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

@Yuriy Petrovskiy's answer is great if you know the levels you want to plot beforehand. If you don't (e.g. because you don't want to plot levels not present in the data), consider using a limit function instead to specify the order:

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) intersect(my_order, x))

From the documentation of scale_x_discrete:

limits
      One of:
      - NULL to use the default scale values
      - A character vector that defines possible values of the scale and their order
      - A function that accepts the existing (automatic) values and returns new ones

Otherwise your graph would end up like this (might be preferable):

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文