ggplot2条形图中的订单栏

Jul*_*iaz 283 r ggplot2 r-faq

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

    Name   Position
1   James  Goalkeeper
2   Frank  Goalkeeper
3   Jean   Defense
4   Steve  Defense
5   John   Defense
6   Tim    Striker
Run Code Online (Sandbox Code Playgroud)

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

p <- ggplot(theTable, aes(x = Position)) + geom_bar(binwidth = 1)
Run Code Online (Sandbox Code Playgroud)

但是图表显示守门员杆然后是防守,最后是前锋一个.我希望图表被排序,以便防守栏最接近y轴,守门员一个,最后是前锋一个.谢谢

Ale*_*own 206

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

ggplot(theTable,
       aes(x=reorder(Position,Position,
                     function(x)-length(x)))) +
       geom_bar()
Run Code Online (Sandbox Code Playgroud)

  • 确实是+1,特别是在这种情况下,我们可以在数字上利用逻辑顺序.如果我们考虑类别的任意排序而我们不想按字母顺序排列,那么直接指定级别就更容易(更容易?). (7认同)
  • 这是最整洁的。无需修改原始数据框 (2认同)
  • 可爱的是,刚刚注意到,如果您想要的只是按长度函数排序并且升序就可以了,那么您可以更简洁地做到这一点,这是我经常想做的事情:`ggplot(theTable,aes(x=reorder) (位置,位置,长度))+geom_bar()` (2认同)

Rei*_*son 202

排序的关键是按所需顺序设置因子的级别.不需要有序因子; 有序因子中的额外信息不是必需的,如果在任何统计模型中使用这些数据,可能会导致错误的参数化 - 多项式对比不适合这样的标称数据.

## 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)
Run Code Online (Sandbox Code Playgroud)

条形图

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

theTable$Position <- factor(theTable$Position, levels = c(...))
Run Code Online (Sandbox Code Playgroud)

  • @Prasad前者是测试的遗留物,所以感谢你指出这一点.就后者而言,我更倾向于明确要求反向排序而不是你使用的`-`,因为从"减去= TRUE"获得意图比在所有其余代码中注意到`-`容易得多. (2认同)
  • @GavinSimpson; 我认为关于`levels(theTable $ Position)< - c(...)`的部分导致了不期望的行为,其中数据帧的实际条目被重新排序,而不仅仅是因子的级别.请参阅[此问题](/sf/ask/166291121/).也许你应该修改或删除这些行? (2认同)
  • 非常赞同安东.我刚刚看到[这个问题](/sf/ask/3832959581/)并且在他们得到使用`levels <-`的错误建议的地方四处寻找.我打算编辑那部分,至少是暂时的. (2认同)
  • @Anton感谢您的建议(以及Gregor的编辑); 我今天永远不会通过`levels < - ()`做到这一点.这是从8年前开始的事情,我不记得当时情况是否有所不同或者我是否只是完全错误,但无论如何,这是错误的,应该删除!谢谢! (2认同)

小智 134

使用scale_x_discrete (limits = ...)指定的巴左右.

positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)
Run Code Online (Sandbox Code Playgroud)

  • 你的解决方案最适合我的情况,因为我想编程绘图,x是由data.frame中的变量表示的任意列.其他建议更难以通过涉及变量的表达式来表达x的顺序的排列.谢谢!如果有兴趣,我可以使用您的建议分享我的解决方案.还有一个问题,添加scale_x_discrete(limits = ...),我发现在图表右侧有一个与条形图一样宽的空白区域.我怎样才能摆脱空白?因为它没有任何目的. (12认同)
  • QIBIN:哇......这里的其他答案都有效,但到目前为止你的答案似乎不仅仅是最简洁和优雅,而是从ggplot框架内思考时最明显的.谢谢. (9认同)

Hol*_*ndl 85

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

ggplot(theTable, aes(x=reorder(Position, -table(Position)[Position]))) + geom_bar()
Run Code Online (Sandbox Code Playgroud)

它与Alex Brown的建议相似,但有点短,无需任何函数定义.

更新

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

require(forcats)

ggplot(theTable, aes(fct_infreq(Position))) + geom_bar()
Run Code Online (Sandbox Code Playgroud)


use*_*472 25

就像reorder()Alex Brown的回答一样,我们也可以使用forcats::fct_reorder().它将基本上对第一个arg中指定的因子进行排序,根据应用指定函数后第二个arg中的值(默认值=中位数,这是我们在这里使用的每个因子级别只有一个值).

令人遗憾的是,在OP的问题中,所需的顺序也是按字母顺序排列的,因为这是创建因子时的默认排序顺序,因此将隐藏此功能实际执行的操作.为了更清楚,我将用"Zoalkeeper"取代"守门员".

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')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 为 Zoalkeeper 点赞 (2认同)

zac*_*ach 21

基于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
Run Code Online (Sandbox Code Playgroud)


Pra*_*ani 18

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

theTable <- transform( theTable,
       Position = ordered(Position, levels = names( sort(-table(Position)))))
Run Code Online (Sandbox Code Playgroud)

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

然后,您的ggplot函数将按计数的降序显示条形.我不知道是否可以选择geom_bar这样做而无需明确创建有序因子.


Rob*_*ald 14

除了@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)             
Run Code Online (Sandbox Code Playgroud)

gplot输出


mpa*_*nco 13

另一种使用重新排序对因子水平进行排序的替代方法。基于计数的升序 (n) 或降序 (-n)。非常类似于fct_reorderforcats包中使用的:

降序排列

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

在此处输入图片说明

升序

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

在此处输入图片说明

数据框:

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))
Run Code Online (Sandbox Code Playgroud)

  • 我认为预先添加计数是最简单的方法 (2认同)

Ale*_*piu 10

我同意zach在dplyr中计算是最好的解决方案.我发现这是最短的版本:

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

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


JCo*_*res 9

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

ggplot(df, aes(x = reorder(Colors, -Qty, sum), y = Qty)) 
+ geom_bar(stat = "identity")  
Run Code Online (Sandbox Code Playgroud)

排序变量(-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
Run Code Online (Sandbox Code Playgroud)

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


Tom*_*mmy 6

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

ggcharts::bar_chart(theTable, Position)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

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