Edit: Cette question a été marquée comme dupliquée, mais les réponses ici ont été essayées et n'ont pas fonctionné car le cas en question est un graphique à courbes, et non un graphique à barres. L'application de ces méthodes produit un graphique avec 5 lignes, une pour chaque année - inutile. Quelqu'un qui a voté pour marquer comme duplicata a-t-il réellement essayé ces approches sur l'ensemble de données fourni avec cette question? Dans l'affirmative, postez une réponse.
Question originale:
Il existe une fonctionnalité dans les tableaux croisés dynamiques Excel qui permet aux axes catégoriels à plusieurs niveaux. J'essaie de trouver un moyen de faire la même chose avec ggplot
(ou tout autre logiciel de traçage en R).
Considérez le jeu de données suivant:
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))
Si cela est importé dans un tableau croisé dynamique Excel, il est facile de créer le graphique suivant:
Notez que l’axe des x a deux niveaux, un pour le trimestre et un pour la variable de regroupement, année. Des axes multiniveaux sont-ils possibles avec ggplot
?
NB: Il y a un bidouillage avec des facettes qui produit quelque chose de similaire, mais ce n'est pas ce que je recherche.
library(ggplot2)
ggplot(df) +
geom_line(aes(x=quarter,y=sales,group=year))+
facet_grid(.~year,scales="free")
Nous utilisons des arguments dans theme
pour supprimer le texte par défaut de l'axe x (axis.title.x
/axis.text.x = element_blank()
) et des marges supplémentaires sont ajoutées (plot.margin
).
Les nouvelles étiquettes sont ajoutées à l'aide de annotate(geom = "text",
. En convertissant l'objet de tracé en grob (ggplot_gtable(ggplot_build(
), il est possible de désactiver le découpage des étiquettes d'axe 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)
Voir aussi la réponse de Nice par @ eipi10 ici: Étiquettes d’axe sur deux lignes avec des variables x imbriquées (année inférieure au mois)
Le code suggéré par Henrik fonctionne et m'a beaucoup aidé! Je pense que la solution a une grande valeur. Mais s'il vous plaît soyez conscient, il y a un petit méfait dans la première ligne du code, ce qui entraîne un mauvais ordre des données. Au lieu de
... aes(x = interaction(year,quarter), ...
cA devrait etre
... aes(x = interaction(quarter,year), ...
Le graphique obtenu contient les données dans le bon ordre.
P.S. J'ai suggéré une modification (qui a été rejetée jusqu'à présent) et, en raison d'un léger manque de réputation, je ne suis pas autorisé à commenter ce que j'aurais plutôt fait.
L'utilisateur Tung
a eu une excellente réponse sur ce fil
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