geom_bar(position = "dodge") 中条的宽度相同 [英] The same width of the bars in geom_bar(position = "dodge")
问题描述
我想用相同宽度的条形绘制绘图.这是我的最小示例代码:
data <- data.frame(A = 字母 [1:17],B = 样本(1:500, 17),C = c(rep(1, 5), rep(2, 6), rep(c(3,4,5), each = 2)))ggplot(数据,aes(x = C, y = B, 标签 = A,填充 = A)) +geom_bar(stat = "identity", position = "dodge") +geom_text(位置= position_dodge(宽度= 0.9),角度= 90)
结果如上图所示:
条形的宽度取决于变量 C
中给定的组中观察的数量.我想让每个条具有相同的宽度.
facet_grid(~C)
有效(条形宽度相同)这不是我的意思:
ggplot(data,aes(x = C, y = B, 标签 = A,填充 = A)) +geom_bar(stat = "identity", position = "dodge") +geom_text(position = position_dodge(width = 0.9), angle = 90) +facet_grid(~C)
我想要的是像第一张图片中那样的情节,但条形的宽度与 C
列中每个级别的观察次数无关.我该怎么做?
geom_bar(width)
改变了条形组的宽度,但第五组中的条形仍然比第一组中的条形宽,所以这不是我问题的答案.
更新
从 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_dodge2(宽度= 0.9,保留=单个"),角度= 90,vjust=0.25)
原答案
正如已经评论过的,你可以像在这个
或者使用交互术语:
数据%>%ggplot(aes(x = 交互(C,A),y = B,填充 = A))+geom_col(位置=闪避")
通过最终将交互转换为数字,您可以根据所需的输出设置 x 轴.通过分组 (group_by
),您可以计算匹配的中断.ggplot 参数周围带有 {}
的花哨的东西很容易在管道中直接使用变量 Breaks
和 C
.
数据%>%变异(gr=as.numeric(interaction(C, A))) %>%group_by(C)%>%变异(Breaks=mean(gr))%>%{ggplot(data=.,aes(x = gr, y = B, 填充 = A, 标签 = A)) +geom_col(position = "dodge") +geom_text(position = position_dodge(width = 0.9), angle = 90) +scale_x_continuous(breaks = unique(.$Breaks),标签 = 唯一(.$C))}
另一种方法是使用方面.使用 space = "free_x"
允许设置与 x 比例的长度成比例的宽度.
图书馆(tidyverse)数据%>%ggplot(aes(x = A, y = B, 填充 = A)) +geom_col(position = "dodge") +facet_grid(~C, scales = "free_x", space = "free_x")
您还可以使用 switch
在底部绘制刻面标签并删除 x 轴标签
数据%>%ggplot(aes(x = A, y = B, 填充 = A)) +geom_col(position = "dodge") +facet_grid(~C, scales = "free_x", space = "free_x", switch = "x") +主题(axis.text.x = element_blank(),axis.ticks.x = element_blank(),strip.background = element_blank())
I would like to draw plot with the same width of the bars. Here's my minimal example code:
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)
The result is shown in the picture above:
The width of the bars is dependent on numbers of observation in group given in variable C
. I want to have each bar to have the same width.
The facet_grid(~C)
works (bars are the same width) it's not what I mean:
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)
What I want is to have plot like in the first picture but with bars's width independent on number of observation in each level from column C
. How can I do it?
[EDIT] geom_bar(width)
changes width of the bars'group but still bars in fifth group are wider than in the first group, so it's not the answer to my question.
Update
Since ggplot2_3.0.0
version you are now be able to use position_dodge2
with 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)
Original answer
As already commented you can do it like in this answer:
Transform A
and C
to factors and add unseen variables using tidyr
's complete
. Since the recent ggplot2
version it is recommended to use geom_col
instead of geom_bar
in cases of stat = "identity"
:
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")
Or work with an interaction term:
data %>%
ggplot(aes(x = interaction(C, A), y = B, fill = A)) +
geom_col(position = "dodge")
And by finally transforming the interaction to numeric you can setup the x-axis according to your desired output. By grouping (group_by
) you can calculate the matching breaks. The fancy stuff with the {}
around the ggplot argument is neseccary to directly use the vaiables Breaks
and C
within the pipe.
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))}
Edit:
Another approach would be to use facets. Using space = "free_x"
allows to set the width proportional to the length of the x scale.
library(tidyverse)
data %>%
ggplot(aes(x = A, y = B, fill = A)) +
geom_col(position = "dodge") +
facet_grid(~C, scales = "free_x", space = "free_x")
You can also plot the facet labels on the bottom using switch
and remove x axis labels
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())
这篇关于geom_bar(position = "dodge") 中条的宽度相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!