提问人:Julio Diaz 提问时间:3/6/2011 最后编辑:Roland EwaldJulio Diaz 更新时间:3/15/2023 访问量:558603
在 ggplot2 条形图中对柱线进行排序
Order Bars in ggplot2 bar graph
问:
我正在尝试制作一个条形图,其中最大的条形最靠近 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 轴,守门员最接近,最后是前锋。 谢谢
答:
您只需要将列指定为有序因子,其中级别按其计数排序:Position
theTable <- transform( theTable,
Position = ordered(Position, levels = names( sort(-table(Position)))))
(请注意,生成列的频率计数。table(Position)
Position
然后,您的函数将按计数递减顺序显示条形图。
我不知道是否有选项可以在不必显式创建有序因子的情况下执行此操作。ggplot
geom_bar
评论
reorder()
reorder()
with(theTable, reorder(Position, as.character(Position), function(x) sum(duplicated(x))))
with(theTable, reorder(Position, as.character(Position), function(x) as.numeric(table(x))))
sort
order
reorder
排序的关键是按照您想要的顺序设置因子的水平。不需要有序因子;有序因子中的额外信息不是必需的,如果这些数据被用于任何统计模型,可能会导致错误的参数化——多项式对比不适合这样的名义数据。
## 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)
从最一般的意义上讲,我们只需要将因子水平设置为所需的顺序。如果未指定,因子的水平将按字母顺序排序。您还可以如上所述在对因子的调用中指定级别顺序,也可以使用其他方法。
theTable$Position <- factor(theTable$Position, levels = c(...))
评论
within
theTable$Position
sort(-table(...))
-
decreasing = TRUE
-
levels(theTable$Position) <- c(...)
levels<-()
@GavinSimpson:是一个强大而有效的解决方案:reorder
ggplot(theTable,
aes(x=reorder(Position,Position,
function(x)-length(x)))) +
geom_bar()
评论
ggplot(theTable,aes(x=reorder(Position,Position,length))+geom_bar()
用于指定条形的顺序。scale_x_discrete (limits = ...)
positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)
评论
我认为已经提供的解决方案过于冗长。使用 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()
评论
一个简单的基于 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
我同意 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
就像 Alex Brown 的回答一样,我们也可以使用 .它基本上会根据应用指定函数后第二个参数中的值对第一个参数中指定的因子进行排序(默认 = 中位数,这就是我们在这里使用的,因为每个因子级别只有一个值)。reorder()
forcats::fct_reorder()
遗憾的是,在 OP 的问题中,所需的顺序也是按字母顺序排列的,因为这是创建因子时的默认排序顺序,因此会隐藏此函数的实际操作。为了更清楚起见,我将“Goalkeeper”替换为“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')
评论
除了 ,还提到
@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)
评论
如果图表列来自数值变量,如下面的数据帧所示,则可以使用更简单的解决方案:
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
当我找到这个线程时,这就是我一直在寻找的答案。希望它对其他人有用。
另一种选择是使用重新排序来对因子的水平进行排序。根据计数按升序 (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))
评论
由于我们只查看单个变量(“位置”)的分布,而不是查看两个变量之间的关系,因此直方图可能是更合适的图形。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
并在 “Score” 变量上使用 geom_histogram()...
ggplot(theTable, aes(x = Score)) + geom_histogram()
对于像“位置”这样的离散数据,我们必须指定一个由美学计算的计算统计数据,以给出柱线高度的 y 值,使用:stat = "count"
ggplot(theTable, aes(x = Position)) + geom_histogram(stat = "count")
注意:奇怪和令人困惑的是,您也可以将其用于连续数据,我认为它提供了一个更美观的图表。stat = "count"
ggplot(theTable, aes(x = Score)) + geom_histogram(stat = "count")
编辑:针对 DebanjanB 的有用建议的扩展答案。
评论
ggplot(theTable, aes(x = Position)) + geom_bar()
我发现没有为此提供“自动”解决方案非常烦人。这就是我在 ggcharts
中创建函数的原因。ggplot2
bar_chart()
ggcharts::bar_chart(theTable, Position)
默认情况下,对条形进行排序并显示水平图。要更改该集 .此外,还消除了杆和轴之间难看的“间隙”。bar_chart()
horizontal = FALSE
bar_chart()
您可以简单地使用以下代码:
ggplot(yourdatasetname, aes(Position, fill = Name)) +
geom_bar(col = "black", size = 2)
评论
如果你不想使用 ,还有 ggpubr 为该函数提供了一个非常有用的参数。您可以按“desc”和“asc”中的条形图进行排序,如下所示:ggplot2
ggbarplot
sort.val
library(dplyr)
library(ggpubr)
# desc
df %>%
count(Position) %>%
ggbarplot(x = "Position",
y = "n",
sort.val = "desc")
# asc
df %>%
count(Position) %>%
ggbarplot(x = "Position",
y = "n",
sort.val = "asc")
创建于 2022-08-14 由 reprex 软件包 (v2.0.1)
如您所见,对条形进行排序非常简单。如果条形图被分组,也可以这样做。查看上面的链接以获取一些有用的示例。
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 with reprex v2.0.2
评论
ggplot2
binwidth = 1
width = 1