344

我正在尝试制作一个条形图,其中最大的条形图最接近 y 轴,最短的条形图最远。所以这有点像我的表

    Name   Position
1   James  Goalkeeper
2   Frank  Goalkeeper
3   Jean   Defense
4   Steve  Defense
5   John   Defense
6   Tim    Striker

所以我正在尝试构建一个条形图,根据位置显示玩家数量

p <- ggplot(theTable, aes(x = Position)) + geom_bar(binwidth = 1)

但图表首先显示的是守门员栏,然后是防守,最后是前锋。我希望对图表进行排序,以便防守条最接近 y 轴,守门员最接近,最后是前锋。谢谢

4

14 回答 14

248

@GavinSimpson:reorder是一个强大而有效的解决方案:

ggplot(theTable,
       aes(x=reorder(Position,Position,
                     function(x)-length(x)))) +
       geom_bar()
于 2012-02-10T17:13:16.537 回答
243

排序的关键是按照您想要的顺序设置因子的水平。不需要有序因子;有序因子中的额外信息不是必需的,如果在任何统计模型中使用这些数据,则可能会导致错误的参数化——多项式对比不适用于诸如此类的标称数据。

## set the levels in order we want
theTable <- within(theTable, 
                   Position <- factor(Position, 
                                      levels=names(sort(table(Position), 
                                                        decreasing=TRUE))))
## plot
ggplot(theTable,aes(x=Position))+geom_bar(binwidth=1)

条形图

在最一般的意义上,我们只需要将因子水平设置为所需的顺序。如果未指定,因子的级别将按字母顺序排序。您还可以如上所述在对 factor 的调用中指定级别顺序,其他方式也是可能的。

theTable$Position <- factor(theTable$Position, levels = c(...))
于 2011-03-06T13:42:41.830 回答
177

用于指定条形scale_x_discrete (limits = ...)的顺序。

positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)
于 2014-12-01T13:20:16.030 回答
102

我认为已经提供的解决方案过于冗长。使用 ggplot 进行频率排序条形图的更简洁的方法是

ggplot(theTable, aes(x=reorder(Position, -table(Position)[Position]))) + geom_bar()

它类似于 Alex Brown 的建议,但更短一些,并且无需任何函数定义即可工作。

更新

我认为我的旧解决方案当时很好,但现在我宁愿使用forcats::fct_infreq按频率对因子水平进行排序:

require(forcats)

ggplot(theTable, aes(fct_infreq(Position))) + geom_bar()
于 2014-12-12T16:58:13.320 回答
37

就像reorder()亚历克斯布朗的回答一样,我们也可以使用forcats::fct_reorder(). 它基本上会在应用指定函数后根据第二个参数中的值对第一个参数中指定的因子进行排序(默认值 = 中位数,我们在这里使用的因为每个因子级别只有一个值)。

遗憾的是,在 OP 的问题中,所需的顺序也是按字母顺序排列的,因为这是您创建因子时的默认排序顺序,因此将隐藏此函数实际在做什么。为了更清楚,我将用“Zoalkeeper”替换“Goalkeeper”。

library(tidyverse)
library(forcats)

theTable <- data.frame(
                Name = c('James', 'Frank', 'Jean', 'Steve', 'John', 'Tim'),
                Position = c('Zoalkeeper', 'Zoalkeeper', 'Defense',
                             'Defense', 'Defense', 'Striker'))

theTable %>%
    count(Position) %>%
    mutate(Position = fct_reorder(Position, n, .desc = TRUE)) %>%
    ggplot(aes(x = Position, y = n)) + geom_bar(stat = 'identity')

在此处输入图像描述

于 2016-12-08T13:22:49.600 回答
25

一个简单的基于 dplyr 的因子重新排序可以解决这个问题:

library(dplyr)

#reorder the table and reset the factor to that ordering
theTable %>%
  group_by(Position) %>%                              # calculate the counts
  summarize(counts = n()) %>%
  arrange(-counts) %>%                                # sort by counts
  mutate(Position = factor(Position, Position)) %>%   # reset factor
  ggplot(aes(x=Position, y=counts)) +                 # plot 
    geom_bar(stat="identity")                         # plot histogram
于 2016-07-29T16:15:32.523 回答
20

除了@HolgerBrandl 提到的forcats::fct_infreq 之外,还有forcats::fct_rev,它颠倒了因子顺序。

theTable <- data.frame(
    Position= 
        c("Zoalkeeper", "Zoalkeeper", "Defense",
          "Defense", "Defense", "Striker"),
    Name=c("James", "Frank","Jean",
           "Steve","John", "Tim"))

p1 <- ggplot(theTable, aes(x = Position)) + geom_bar()
p2 <- ggplot(theTable, aes(x = fct_infreq(Position))) + geom_bar()
p3 <- ggplot(theTable, aes(x = fct_rev(fct_infreq(Position)))) + geom_bar()

gridExtra::grid.arrange(p1, p2, p3, nrow=3)             

gplot 输出

于 2018-02-24T04:19:22.870 回答
19

您只需将Position列指定为有序因子,其中级别按其计数排序:

theTable <- transform( theTable,
       Position = ordered(Position, levels = names( sort(-table(Position)))))

(请注意,table(Position)产生Position列的频率计数。)

然后您的ggplot函数将按计数的递减顺序显示条形图。我不知道是否有一个选项可以在geom_bar不必显式创建有序因子的情况下执行此操作。

于 2011-03-06T04:44:07.310 回答
17

另一种替代方法是使用重新排序来对因子的水平进行排序。以升序 (n) 或降序 (-n) 为基础的计数。非常类似于使用包fct_reorder中的那个forcats

降序排列

df %>%
  count(Position) %>%
  ggplot(aes(x = reorder(Position, -n), y = n)) +
  geom_bar(stat = 'identity') +
  xlab("Position")

在此处输入图像描述

升序

df %>%
  count(Position) %>%
  ggplot(aes(x = reorder(Position, n), y = n)) +
  geom_bar(stat = 'identity') +
  xlab("Position")

在此处输入图像描述

数据框:

df <- structure(list(Position = structure(c(3L, 3L, 1L, 1L, 1L, 2L), .Label = c("Defense", 
"Striker", "Zoalkeeper"), class = "factor"), Name = structure(c(2L, 
1L, 3L, 5L, 4L, 6L), .Label = c("Frank", "James", "Jean", "John", 
"Steve", "Tim"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L))
于 2019-02-03T15:27:03.433 回答
14

如果图表列来自下面数据框中的数字变量,则可以使用更简单的解决方案:

ggplot(df, aes(x = reorder(Colors, -Qty, sum), y = Qty)) 
+ geom_bar(stat = "identity")  

排序变量(-Qty)前面的减号控制排序方向(升序/降序)

以下是一些测试数据:

df <- data.frame(Colors = c("Green","Yellow","Blue","Red","Yellow","Blue"),  
                 Qty = c(7,4,5,1,3,6)
                )

**Sample data:**
  Colors Qty
1  Green   7
2 Yellow   4
3   Blue   5
4    Red   1
5 Yellow   3
6   Blue   6

当我找到这个帖子时,这就是我正在寻找的答案。希望对其他人有用。

于 2018-08-03T07:17:19.517 回答
13

我同意 zach 的观点,即在 dplyr 中计数是最好的解决方案。我发现这是最短的版本:

dplyr::count(theTable, Position) %>%
          arrange(-n) %>%
          mutate(Position = factor(Position, Position)) %>%
          ggplot(aes(x=Position, y=n)) + geom_bar(stat="identity")

这也将比预先重新排序因子水平要快得多,因为计数是在 dplyr 而不是在 ggplot 或 using 中完成的table

于 2016-07-31T19:11:08.767 回答
8

我发现ggplot2不为此提供“自动”解决方案非常烦人。这就是为什么我bar_chart()ggcharts.

ggcharts::bar_chart(theTable, Position)

在此处输入图像描述

默认情况下bar_chart()对条形图进行排序并显示水平图。要更改该设置 horizontal = FALSE。此外,bar_chart()消除了条形和轴之间难看的“间隙”。

于 2020-04-12T15:18:52.703 回答
4

由于我们只查看单个变量(“位置”)的分布,而不是查看两个变量之间的关系,那么直方图可能是更合适的图表。ggplot 有geom_histogram()使它变得容易:

ggplot(theTable, aes(x = Position)) + geom_histogram(stat="count")

在此处输入图像描述

使用 geom_histogram():

我认为geom_histogram( ) 有点古怪,因为它以不同的方式处理连续数据和离散数据。

对于连续数据,您可以只使用不带参数的geom_histogram() 。例如,如果我们添加一个数字向量“Score”......

    Name   Position   Score  
1   James  Goalkeeper 10
2   Frank  Goalkeeper 20
3   Jean   Defense    10
4   Steve  Defense    10
5   John   Defense    20
6   Tim    Striker    50

并在“分数”变量上使用 geom_histogram()...

ggplot(theTable, aes(x = Score)) + geom_histogram()

在此处输入图像描述

对于像“位置”这样的离散数据,我们必须指定一个由美学计算的计算统计数据,以使用 y 值给出条形高度的 y 值stat = "count"

 ggplot(theTable, aes(x = Position)) + geom_histogram(stat = "count")

注意:奇怪且令人困惑的是,您也可以将stat = "count"其用于连续数据,我认为它提供了一个更美观的图表。

ggplot(theTable, aes(x = Score)) + geom_histogram(stat = "count")

在此处输入图像描述

编辑:响应DebanjanB的有用建议的扩展答案。

于 2019-02-14T11:41:42.667 回答
-1

您可以简单地使用以下代码:

ggplot(yourdatasetname, aes(Position, fill = Name)) + 
     geom_bar(col = "black", size = 2)

在此处输入图像描述

于 2020-08-05T21:30:06.737 回答