我要做一个柱状图,其中最大的柱状图离y轴最近,最短的柱状图离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轴,守门员条,最后是前锋条。 谢谢


当前回答

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

遗憾的是,在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')

其他回答

library(ggplot2)
library(magrittr)

dd <- tibble::tribble(
    ~Name,    ~Position,
  "James", "Goalkeeper",
  "Frank", "Goalkeeper",
   "Jean",    "Defense",
   "John",    "Defense",
  "Steve",    "Defense",
    "Tim",    "Striker"
  )


dd %>% ggplot(aes(x = forcats::fct_infreq(Position))) + geom_bar()

于2022-08-30使用reprex v2.0.2创建

你可以简单地使用下面的代码:

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

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

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

除了forcats::fct_infreq之外,由 @HolgerBrandl,有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)             

我同意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或使用table中完成的。