ggplot折线图中的多行x轴标签

Posted

技术标签:

【中文标题】ggplot折线图中的多行x轴标签【英文标题】:Multi-row x-axis labels in ggplot line chart 【发布时间】:2014-01-01 12:07:48 【问题描述】:

编辑:此问题已被标记为重复,但已尝试回复 here 并没有工作,因为所讨论的案例是折线图,而不是条形图。应用这些方法会生成一个包含 5 条线的图表,每年 1 条线 - 没用。投票标记为重复的人是否真的在这个问题提供的样本数据集上尝试了这些方法?如果是这样,请发布作为答案。

原问题:

Excel 数据透视图中有一个功能允许多级分类轴。我正在尝试找到一种方法来使用ggplot(或 R 中的任何其他绘图包)做同样的事情。

考虑以下数据集:

set.seed(1)
df=data.frame(year=rep(2009:2013,each=4),
              quarter=rep(c("Q1","Q2","Q3","Q4"),5),
              sales=40:59+rnorm(20,sd=5))

如果将其导入 Excel 数据透视表,则可以直接创建以下图表:

注意 x 轴有两个级别,一个代表季度,一个代表分组变量年。 ggplot 可以实现多级轴吗?

注意:有一个带有 facets 的 hack 会产生类似的东西,但这不是我想要的。

library(ggplot2)
ggplot(df) +
  geom_line(aes(x=quarter,y=sales,group=year))+
  facet_grid(.~year,scales="free")

【问题讨论】:

【参考方案1】:

使用annotate(geom = "text", 添加新标签。在coord_cartesian 中使用clip = "off" 关闭x 轴标签的剪裁。

使用 theme 添加额外的边距 (plot.margin) 并删除 (element_blank()) x 轴文本 (axis.title.x, axis.text.x) 和垂直网格线 (panel.grid.x)。

library(ggplot2)

ggplot(data = df, aes(x = interaction(year, quarter, lex.order = TRUE), 
                      y = sales, group = 1)) +
  geom_line(colour = "blue") +
  annotate(geom = "text", x = seq_len(nrow(df)), y = 34, label = df$quarter, size = 4) +
  annotate(geom = "text", x = 2.5 + 4 * (0:4), y = 32, label = unique(df$year), size = 6) +
  coord_cartesian(ylim = c(35, 65), expand = FALSE, clip = "off") +
  theme_bw() +
  theme(plot.margin = unit(c(1, 1, 4, 1), "lines"),
        axis.title.x = element_blank(),
        axis.text.x = element_blank(),
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank())


也可以在这里查看@eipi10 的精彩回答:Axis labels on two lines with nested x variables (year below months)

【讨论】:

非常好!另外,x=interaction(year,quarter) 的使用对我来说是新的。 老兄,这个答案太棒了 @Henrik 如果我的数据中有几个月而不是quarter=rep(c("Jan","Feb","Mar","May"),5) 中的季度,我该怎么做?【参考方案2】:

Henrik 建议的代码确实有效,对我帮助很大!我认为该解决方案具有很高的价值。但请注意,第一行代码有一个小错误,导致数据顺序错误。 而不是

... aes(x = interaction(year,quarter), ...

应该是

... aes(x = interaction(quarter,year), ...

生成的图形具有正确顺序的数据。

附:我建议了一个编辑(直到现在都被拒绝了),并且由于缺乏声誉,我不能发表评论,我宁愿这样做。

【讨论】:

【参考方案3】:

用户Tung 有一个很好的答案on this thread

library(tidyverse)
library(lubridate)
library(scales)

set.seed(123)
df <- tibble(
  date = as.Date(41000:42000, origin = "1899-12-30"), 
  value = c(rnorm(500, 5), rnorm(501, 10))
)

# create year column for facet
df <- df %>% 
  mutate(year = as.factor(year(date)))

p <- ggplot(df, aes(date, value)) + 
  geom_line() + 
  geom_vline(xintercept = as.numeric(df$date[yday(df$date) == 1]), color = "grey60") + 
  scale_x_date(date_labels = "%b", 
               breaks = pretty_breaks(),
               expand = c(0, 0)) +
  # switch the facet strip label to the bottom
  facet_grid(.~ year, space = 'free_x', scales = 'free_x', switch = 'x') +
  labs(x = "") +
  theme_classic(base_size = 14, base_family = 'mono') +
  theme(panel.grid.minor.x = element_blank()) + 
  # remove facet spacing on x-direction
  theme(panel.spacing.x = unit(0,"line")) +
  # switch the facet strip label to outside 
  # remove background color
  theme(strip.placement = 'outside',
        strip.background.x = element_blank())
p

【讨论】:

这是一个相当有创意的解决方案(使用隐藏面)!

以上是关于ggplot折线图中的多行x轴标签的主要内容,如果未能解决你的问题,请参考以下文章

excel折线图中怎么设置不等距的Y轴,可以设置吗?

python--seaborn折线图

多行中的 D3 折线图轴文本标签

Android MPAndroidChart 折线图设置哪些属性?

使用 ggplot 在折线图中仅绘制 x 轴上的日期向量的值

NVD3如何删除折线图中的Y轴,并在移除后利用Y轴的空间