Подтвердить что ты не робот

Многострочные метки оси x в линейной диаграмме ggplot

Изменить: Этот вопрос был отмечен как дублированный, но ответы здесь были опробованы и не работали, потому что рассматриваемый случай это линейная диаграмма, а не гистограмма. Применение этих методов дает диаграмму с 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?

NB: Есть хак с фасетками, которые производят нечто подобное, но это не то, что я ищу.

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

4b9b3361

Ответ 1

Мы используем аргументы в theme для удаления текста по оси x по умолчанию (axis.title.x/axis.text.x = element_blank()) и добавляются дополнительные поля (plot.margin).

Новые метки добавляются с помощью annotate(geom = "text",. Преобразуя объект plot в grob (ggplot_gtable(ggplot_build(), обрезание меток оси x может быть отключено.

library(ggplot2)
g1 <- ggplot(data = df, aes(x = interaction(year, quarter, lex.order = TRUE), 
                            y = sales, group = 1)) +
  geom_line(colour = "blue") +
  coord_cartesian(ylim = c(35, 65), expand = FALSE) +
  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) +
  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())


# remove clipping of x axis labels
g2 <- ggplot_gtable(ggplot_build(g1))
g2$layout$clip[g2$layout$name == "panel"] <- "off"
grid::grid.draw(g2)

введите описание изображения здесь


См. также хороший ответ от @eipi10 здесь: Предотвращать многократное отображение года с временными рядами

Ответ 2

Предлагаемый код Хенрика действительно работает и мне очень помог! Я думаю, что решение имеет большое значение. Но, пожалуйста, имейте в виду, что в первой строке кода есть небольшая ошибка, что приводит к неправильному порядку данных. Вместо

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

он должен быть

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

Полученный рисунок имеет данные в правильном порядке.

enter image description here

P.S. Я предложил изменение (которое было отклонено до сих пор), и из-за небольшой нехватки репутации мне не разрешено комментировать, что бы я сделал.