geom_bar(position = "dodge") 中条的宽度相同
Posted
技术标签:
【中文标题】geom_bar(position = "dodge") 中条的宽度相同【英文标题】:The same width of the bars in geom_bar(position = "dodge") 【发布时间】:2022-01-19 08:45:21 【问题描述】:我想绘制具有相同宽度的条形图。这是我的最小示例代码:
data <- data.frame(A = letters[1:17],
B = sample(1:500, 17),
C = c(rep(1, 5), rep(2, 6), rep(c(3,4,5), each = 2)))
ggplot(data,
aes(x = C, y = B, label = A,
fill = A)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(position = position_dodge(width = 0.9), angle = 90)
结果如上图所示:
条形的宽度取决于变量C
中给出的组中观察的数量。我希望每个条具有相同的宽度。
facet_grid(~C)
有效(条的宽度相同)这不是我的意思:
ggplot(data,
aes(x = C, y = B, label = A,
fill = A)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(position = position_dodge(width = 0.9), angle = 90) +
facet_grid(~C)
我想要的是像第一张图片一样绘制,但条形的宽度独立于C
列中每个级别的观察次数。我该怎么做?
[编辑] geom_bar(width)
改变了条形组的宽度,但第五组的条形仍然比第一组宽,所以这不是我问题的答案。
【问题讨论】:
我不知道如何在不更改aes(x = )
的情况下做到这一点。如果您的 geom_bar()
中的观测值数量不均匀,则该函数会将单个观测值的宽度限制为组的宽度,以便所有观测值都可见。
试试这个:***.com/questions/11020437/…。因此,对于您的数据,您必须像这样转换它:dat.all <- rbind(data[,c(1,3,2)], cbind(expand.grid(A=levels(data$A),C=levels(data$C)), B=NA))
但我认为分面网格是更好的选择。
致未来的自己:如果问题是how to have a fixed width in geom_bar with position_dodge?
,请直接从手册中尝试这个geom_bar(position = position_dodge(preserve = "single"))
。 [未经测试 OP 的问题]
【参考方案1】:
更新
从ggplot2_3.0.0
版本开始,您现在可以使用position_dodge2
和preserve = c("total", "single")
ggplot(data,aes(x = C, y = B, label = A, fill = A)) +
geom_col(position = position_dodge2(width = 0.9, preserve = "single")) +
geom_text(position = position_dodge2(width = 0.9, preserve = "single"), angle = 90, vjust=0.25)
原答案
正如已经评论的那样,您可以像answer 那样做:
将A
和C
转换为因子并使用tidyr
的complete
添加看不见的变量。由于最近的ggplot2
版本建议在stat = "identity"
的情况下使用geom_col
而不是geom_bar
:
data %>%
as.tibble() %>%
mutate_at(c("A", "C"), as.factor) %>%
complete(A,C) %>%
ggplot(aes(x = C, y = B, fill = A)) +
geom_col(position = "dodge")
或使用交互术语:
data %>%
ggplot(aes(x = interaction(C, A), y = B, fill = A)) +
geom_col(position = "dodge")
通过最终将交互转换为数字,您可以根据所需的输出设置 x 轴。通过分组 (group_by
),您可以计算匹配中断。 ggplot 参数周围带有 的花哨的东西是直接使用管道内的变量
Breaks
和C
的必要条件。
data %>%
mutate(gr=as.numeric(interaction(C, A))) %>%
group_by(C) %>%
mutate(Breaks=mean(gr)) %>%
ggplot(data=.,aes(x = gr, y = B, fill = A, label = A)) +
geom_col(position = "dodge") +
geom_text(position = position_dodge(width = 0.9), angle = 90 ) +
scale_x_continuous(breaks = unique(.$Breaks),
labels = unique(.$C))
编辑:
另一种方法是使用构面。使用space = "free_x"
可以设置宽度与x 刻度的长度成比例。
library(tidyverse)
data %>%
ggplot(aes(x = A, y = B, fill = A)) +
geom_col(position = "dodge") +
facet_grid(~C, scales = "free_x", space = "free_x")
您还可以使用switch
在底部绘制分面标签并删除 x 轴标签
data %>%
ggplot(aes(x = A, y = B, fill = A)) +
geom_col(position = "dodge") +
facet_grid(~C, scales = "free_x", space = "free_x", switch = "x") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.background = element_blank())
【讨论】:
但我还有一个问题 -as.numeric(interaction(C,A))
中的数字是什么意思,R 如何将交互向量转换为数字?我将代码用于其他数据,as.numeric(interaction(C,A))
的结果是无序数字的向量,并且绘图看起来不像它应该的方式(图中的条形顺序错误)
我认为这是一个级别排序问题。为了清楚地说明这一点,检查这个小例子并将这个as.numeric(factor(c("a","b","c")))
输出与as.numeric(factor(c("a","b","c"),levels = c("b","c","a")))
输出进行比较。因此,您必须对interaction()
适当的因子水平进行重新排序。以上是关于geom_bar(position = "dodge") 中条的宽度相同的主要内容,如果未能解决你的问题,请参考以下文章
使用 geom_bar 和 stat="identity" 在均值处绘制 hline
如何在时间序列图中使用 geom_bar stat="identity" 设置 Bin Width?