144 votes

Superposition d'histogrammes avec ggplot2 en R

Je suis nouveau dans R et j'essaie de tracer 3 histogrammes sur le même graphique. Tout fonctionne bien, mais mon problème est que l'on ne voit pas où 2 histogrammes se chevauchent - ils semblent plutôt coupés.

Lorsque je réalise des diagrammes de densité, tout est parfait : chaque courbe est entourée d'une ligne noire, et les couleurs sont différentes là où les courbes se chevauchent.

Quelqu'un peut-il me dire si l'on peut obtenir quelque chose de similaire avec les histogrammes de la première image ? Voici le code que j'utilise :

lowf0 <-read.csv (....)
mediumf0 <-read.csv (....)
highf0 <-read.csv(....)
lowf0$utt<-'low f0'
mediumf0$utt<-'medium f0'
highf0$utt<-'high f0'
histogram<-rbind(lowf0,mediumf0,highf0)
ggplot(histogram, aes(f0, fill = utt)) + geom_histogram(alpha = 0.2)

4 votes

Les hyperliens vers l'histogramme et le graphique de densité sont rompus.

292voto

kohske Points 30437

En utilisant l'échantillon de données de @joran,

ggplot(dat, aes(x=xx, fill=yy)) + geom_histogram(alpha=0.2, position="identity")

Notez que la position par défaut de geom_histogram est "stack".

voir "réglage de la position" de cette page :

geom_histogram documentation

34 votes

Je pense que cela devrait être la première réponse car cela évite de répéter le code.

7 votes

position = 'identity' n'est pas seulement une réponse plus lisible, elle s'accorde mieux avec des tracés plus compliqués, tels que des appels mixtes à aes() y aes_string() .

2 votes

Cette réponse affichera aussi automatiquement une légende aux couleurs, alors que la réponse de @joran ne le fera pas. La légende peut ensuite être modifiée en utilisant, par exemple, les fonctions suivantes scale_fill_manual() . Cette fonction peut également être utilisée pour modifier les couleurs dans les histogrammes.

124voto

joran Points 68079

Votre code actuel :

ggplot(histogram, aes(f0, fill = utt)) + geom_histogram(alpha = 0.2)

dit ggplot pour construire un l'histogramme en utilisant toutes les valeurs dans f0 puis de colorer les barres de cet histogramme unique en fonction de la variable utt .

Ce que vous voulez plutôt, c'est créer trois histogrammes distincts, avec un mélange alpha pour qu'ils soient visibles les uns à travers les autres. Vous voulez donc probablement utiliser trois appels distincts à geom_histogram où chacun a son propre cadre de données et son propre remplissage :

ggplot(histogram, aes(f0)) + 
    geom_histogram(data = lowf0, fill = "red", alpha = 0.2) + 
    geom_histogram(data = mediumf0, fill = "blue", alpha = 0.2) +
    geom_histogram(data = highf0, fill = "green", alpha = 0.2) +

Voici un exemple concret avec quelques résultats :

dat <- data.frame(xx = c(runif(100,20,50),runif(100,40,80),runif(100,0,30)),yy = rep(letters[1:3],each = 100))

ggplot(dat,aes(x=xx)) + 
    geom_histogram(data=subset(dat,yy == 'a'),fill = "red", alpha = 0.2) +
    geom_histogram(data=subset(dat,yy == 'b'),fill = "blue", alpha = 0.2) +
    geom_histogram(data=subset(dat,yy == 'c'),fill = "green", alpha = 0.2)

ce qui donne quelque chose comme ceci :

enter image description here

Modifié pour corriger les fautes de frappe ; vous vouliez du remplissage, pas de la couleur.

7 votes

Cela ne fonctionne pas lorsque le sous-ensemble a une taille différente. Une idée pour résoudre ce problème ? (Par exemple, utiliser des données avec 100 points sur "a", 50 sur "b").

3 votes

L'inconvénient de cette approche est que j'ai eu du mal à obtenir l'affichage d'une légende (mais cela pourrait être dû à mon manque de connaissances). L'autre réponse ci-dessous par @kohske affichera par défaut une légende qui peut ensuite être modifiée (ainsi que les couleurs spécifiques affichées sur l'histogramme) avec, par ex. scale_fill_manual() .

1 votes

Exactement, comment peut-on ajouter une légende à cela ?

47voto

Cybernetic Points 2882

Bien que quelques lignes seulement soient nécessaires pour tracer des histogrammes multiples ou superposés dans ggplot2, les résultats ne sont pas toujours satisfaisants. Il faut utilisation appropriée des bordures et des couleurs pour que l'œil puisse différencier les histogrammes .

Les fonctions suivantes équilibrent couleurs des bordures, opacités et tracés de densité superposés pour permettre au spectateur de différencier les distributions .

Histogramme simple :

plot_histogram <- function(df, feature) {
    plt <- ggplot(df, aes(x=eval(parse(text=feature)))) +
    geom_histogram(aes(y = ..density..), alpha=0.7, fill="#33AADE", color="black") +
    geom_density(alpha=0.3, fill="red") +
    geom_vline(aes(xintercept=mean(eval(parse(text=feature)))), color="black", linetype="dashed", size=1) +
    labs(x=feature, y = "Density")
    print(plt)
}

Histogramme multiple :

plot_multi_histogram <- function(df, feature, label_column) {
    plt <- ggplot(df, aes(x=eval(parse(text=feature)), fill=eval(parse(text=label_column)))) +
    geom_histogram(alpha=0.7, position="identity", aes(y = ..density..), color="black") +
    geom_density(alpha=0.7) +
    geom_vline(aes(xintercept=mean(eval(parse(text=feature)))), color="black", linetype="dashed", size=1) +
    labs(x=feature, y = "Density")
    plt + guides(fill=guide_legend(title=label_column))
}

Utilisation :

Tout simplement passer votre cadre de données dans les fonctions ci-dessus ainsi que les arguments souhaités :

plot_histogram(iris, 'Sepal.Width')

enter image description here

plot_multi_histogram(iris, 'Sepal.Width', 'Species')

enter image description here

El paramètre supplémentaire dans plot_multi_histogram est le nom de la colonne contenant les étiquettes des catégories.

Nous pouvons voir cela de manière plus spectaculaire en créant un cadre de données avec de nombreux moyens de distribution différents :

a <-data.frame(n=rnorm(1000, mean = 1), category=rep('A', 1000))
b <-data.frame(n=rnorm(1000, mean = 2), category=rep('B', 1000))
c <-data.frame(n=rnorm(1000, mean = 3), category=rep('C', 1000))
d <-data.frame(n=rnorm(1000, mean = 4), category=rep('D', 1000))
e <-data.frame(n=rnorm(1000, mean = 5), category=rep('E', 1000))
f <-data.frame(n=rnorm(1000, mean = 6), category=rep('F', 1000))
many_distros <- do.call('rbind', list(a,b,c,d,e,f))

Passage du cadre de données comme précédemment (et élargissement du graphique en utilisant les options) :

options(repr.plot.width = 20, repr.plot.height = 8)
plot_multi_histogram(many_distros, 'n', 'category')

enter image description here

Pour ajouter un ligne verticale séparée pour chaque distribution :

plot_multi_histogram <- function(df, feature, label_column, means) {
    plt <- ggplot(df, aes(x=eval(parse(text=feature)), fill=eval(parse(text=label_column)))) +
    geom_histogram(alpha=0.7, position="identity", aes(y = ..density..), color="black") +
    geom_density(alpha=0.7) +
    geom_vline(xintercept=means, color="black", linetype="dashed", size=1)
    labs(x=feature, y = "Density")
    plt + guides(fill=guide_legend(title=label_column))
}

Le seul changement par rapport au précédent plot_multi_histogramme est l'addition de means aux paramètres, et en modifiant les geom_vline pour accepter des valeurs multiples.

Utilisation :

options(repr.plot.width = 20, repr.plot.height = 8)
plot_multi_histogram(many_distros, "n", 'category', c(1, 2, 3, 4, 5, 6))

Résultat :

enter image description here

Puisque j'ai défini les moyens explicitement dans many_distros Je peux simplement les faire passer. Vous pouvez également les calculer dans la fonction et les utiliser de cette façon.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X