【问题标题】:Multi-row x-axis labels in ggplot line chartggplot折线图中的多行x轴标签
【发布时间】: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")

【问题讨论】:

    标签: r ggplot2


    【解决方案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
      

      【讨论】:

      • 这是一个相当有创意的解决方案(使用隐藏面)!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 2020-08-11
      • 2015-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多