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 &lt;- 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_dodge2preserve = 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 那样做: 将AC 转换为因子并使用tidyrcomplete 添加看不见的变量。由于最近的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 参数周围带有 的花哨的东西是直接使用管道内的变量BreaksC 的必要条件。

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()函数绘制条形图

如何在时间序列图中使用 geom_bar stat="identity" 设置 Bin Width?

R语言 柱状图 geom_col 与 geom_bar 与geom_histogram(直方图)

防止第二个传说

如何在 ggplot2 中的 position_dodge 中将单个条形位置与多个条形居中