Barplot with double x-axis labels

huangapple go评论66阅读模式
英文:

Barplot with double x-axis labels

问题

我需要创建一个条形图,显示三种不同服务的每周销售数量。我需要将日历周和月份作为x轴标签之一。

以下是我的代码:

sample <- data.frame(service_type = c("A","B","C","A","B","C","A","B","C","A","B","C","A","B","C","A","B","C","A","B","C"),
                     qty = c(38,185,87,29,12,133,2,14,31,2,9,59,60,43,137,135,31,159,15,32,1),
                     year_week = c("2022 - CW02","2022 - CW02","2022 - CW02","2022 - CW03","2022 - CW03","2022 - CW03","2022 - CW04","2022 - CW04","2022 - CW04","2022 - CW05","2022 - CW05","2022 - CW05","2022 - CW06","2022 - CW06","2022 - CW06","2022 - CW07","2022 - CW07","2022 - CW07","2022 - CW08","2022 - CW08","2022 - CW08"),
                     xlabel2 = c("Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Jan-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22","Feb-22")
)

## 使用 annotate
sample %>%
  ggplot() +
  aes(x = year_week, fill = service_type, weight = qty) +
  geom_bar(position = "dodge") +
  scale_fill_hue(direction = 1) +
  theme_minimal() +
  theme(legend.position = "left", axis.text.x = element_text(angle=90, hjust=1)) +
  coord_cartesian(clip = "off") +
  annotate(geom = "text",
           x = 1:(nrow(sample)/3),
           y = min(sample$qty),
           label = unique(sample$xlabel2),
           vjust = 1,
           angle = 90)

## 使用 facet_wrap
sample %>%
  ggplot() +
  aes(x = year_week, fill = service_type, weight = qty) +
  geom_bar(position = "dodge") +
  scale_fill_hue(direction = 1) +
  theme_minimal() +
  theme(legend.position = "left", axis.text.x = element_text(angle=90, hjust=1)) +
  facet_wrap(~xlabel2, strip.position = "bottom") +
  theme(strip.placement = "outside")

第一次尝试使用 annotate,但我收到错误信息'Error in annotate(): ! Unequal parameter lengths: x (7), label (2)'

第二次尝试使用 facet_wrap,图表重复了第一个轴标签两次,不符合我的要求。

我不确定这些方法中是否有一个是正确的。非常感谢任何能帮助我的人。

谢谢!

英文:

I need to build a barplot showing the sold qty of three different services on a weekly basis. I need to add as x-axis label either the calendar week and the month.
See the image for an example:

Barplot with double x-axis labels

Here is my code:

sample &lt;- data.frame(service_type = c(&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;),
qty = c(38,185,87,29,12,133,2,14,31,2,9,59,60,43,137,135,31,159,15,32,1),
year_week = c(&quot;2022 - CW02&quot;,&quot;2022 - CW02&quot;,&quot;2022 - CW02&quot;,&quot;2022 - CW03&quot;,&quot;2022 - CW03&quot;,&quot;2022 - CW03&quot;,&quot;2022 - CW04&quot;,&quot;2022 - CW04&quot;,&quot;2022 - CW04&quot;,&quot;2022 - CW05&quot;,&quot;2022 - CW05&quot;,&quot;2022 - CW05&quot;,&quot;2022 - CW06&quot;,&quot;2022 - CW06&quot;,&quot;2022 - CW06&quot;,&quot;2022 - CW07&quot;,&quot;2022 - CW07&quot;,&quot;2022 - CW07&quot;,&quot;2022 - CW08&quot;,&quot;2022 - CW08&quot;,&quot;2022 - CW08&quot;),
xlabel2 = c(&quot;Jan-22&quot;,&quot;Jan-22&quot;,&quot;Jan-22&quot;,&quot;Jan-22&quot;,&quot;Jan-22&quot;,&quot;Jan-22&quot;,&quot;Jan-22&quot;,&quot;Jan-22&quot;,&quot;Jan-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;,&quot;Feb-22&quot;)
)
## To use annotate
sample %&gt;%
#arrange(desc(dat_cal_week_id)) %&gt;%
ggplot() +
aes(x = year_week, fill = service_type, weight = qty) +
geom_bar(position = &quot;dodge&quot;) +
scale_fill_hue(direction = 1) +
theme_minimal() +
#theme(legend.position = &quot;left&quot;, axis.text.x = element_text(angle=90, hjust=1)) +
theme(legend.position = &quot;left&quot;, axis.text.x = element_blank()) +
coord_cartesian(clip = &quot;off&quot;) +
annotate(geom = &quot;text&quot;,
x = 1:(nrow(sample)/3),
y = min(sample$qty),
label = unique(sample$xlabel2),
vjust = 1,
angle = 90)
## Using facet_wrap
sample %&gt;%
#arrange(desc(dat_cal_week_id)) %&gt;%
ggplot() +
aes(x = year_week, fill = service_type, weight = qty) +
geom_bar(position = &quot;dodge&quot;) +
scale_fill_hue(direction = 1) +
theme_minimal() +
theme(legend.position = &quot;left&quot;, axis.text.x = element_text(angle=90, hjust=1)) +
facet_wrap(~xlabel2, strip.position = &quot;bottom&quot;) +
theme(strip.placement = &quot;outside&quot;)

The first try is with annotate but I receive the error 'Error in annotate():
! Unequal parameter lengths: x (7), label (2)'

The second try is with facet_wrap and the plot is repeating the first axis labels twice and it's not what I'm looking for
See image

I'm not sure that any of these approaches are correct.
I really appreciate anyone who can help me with this.
Thanks
​ ​ ​ ​

答案1

得分: 1

一个选择是使用分面,但具有自由比例,即scales="free_x"。另外,至少对于你的示例数据,我会切换到facet_grid,因为它允许使用space="free_x",这样我们可以获得每个分面等宽的条形图:

library(ggplot2)

sample$xlabel2 <- factor(sample$xlabel2, c("Jan-22", "Feb-22"))

ggplot(sample) +
  aes(x = year_week, fill = service_type, weight = qty) +
  geom_bar(position = "dodge") +
  scale_fill_hue(direction = 1) +
  theme_minimal() +
  theme(legend.position = "left", axis.text.x = element_text(angle = 90, hjust = 1)) +
  facet_grid(~xlabel2, switch = "x", scales = "free_x", space = "free_x") +
  theme(strip.placement = "outside")

Barplot with double x-axis labels


<details>
<summary>英文:</summary>
One option would be to use facetting but with a free scale, i.e. `scales=&quot;free_x&quot;`. Additionally at least for your example data I would switch to `facet_grid` as it allows to use `space=&quot;free_x&quot;` so that we get bars of equal width per facet:

library(ggplot2)

sample$xlabel2 <- factor(sample$xlabel2, c("Jan-22", "Feb-22"))

ggplot(sample) +
aes(x = year_week, fill = service_type, weight = qty) +
geom_bar(position = "dodge") +
scale_fill_hue(direction = 1) +
theme_minimal() +
theme(legend.position = "left", axis.text.x = element_text(angle = 90, hjust = 1)) +
facet_grid(~xlabel2, switch = "x", scales = "free_x", space = "free_x") +
theme(strip.placement = "outside")


[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/YbwsK.png
</details>
# 答案2
**得分**: 0
如果您将 `year_week` 转换为 `Date` 对象,可以在 `scale_x_date()` 中使用 `sec.axis`:

library(dplyr)
library(ggplot2)

sample <- sample %>%
mutate(date = as.Date(paste0(year_week, 1), "%Y - CW%U%u"))

sample %>%
ggplot() +
aes(x = date, fill = service_type, weight = qty) +
geom_bar(position = "dodge") +
scale_fill_hue(direction = 1) +
scale_x_date(
date_labels = "%Y - CW%U",
date_breaks = "1 week",
sec.axis = dup_axis(
breaks = as.Date(paste0("15-", unique(sample$xlabel2)), "%d-%b-%y"),
labels = (x) format(x, "%b-%y")
)
) +
theme_minimal() +
theme(legend.position = "left", axis.text.x.bottom = element_text(angle=90, hjust=1))

[![][1]][1]
<details>
<summary>英文:</summary>
If you convert `year_week` to a `Date` object, you can use `sec.axis` in `scale_x_date()`:

library(dplyr)
library(ggplot2)

sample <- sample %>%
mutate(date = as.Date(paste0(year_week, 1), "%Y - CW%U%u"))

sample %>%
ggplot() +
aes(x = date, fill = service_type, weight = qty) +
geom_bar(position = "dodge") +
scale_fill_hue(direction = 1) +
scale_x_date(
date_labels = "%Y - CW%U",
date_breaks = "1 week",
sec.axis = dup_axis(
breaks = as.Date(paste0("15-", unique(sample$xlabel2)), "%d-%b-%y"),
labels = (x) format(x, "%b-%y")
)
) +
theme_minimal() +
theme(legend.position = "left", axis.text.x.bottom = element_text(angle=90, hjust=1))

[![][1]][1]
[1]: https://i.stack.imgur.com/RIzxa.png
</details>

huangapple
  • 本文由 发表于 2023年3月31日 16:47:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75896553.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定