ggplot2: histogramme avec courbe normale
j'ai essayé de superposer une courbe normale sur mon histogramme avec ggplot 2.
Ma formule:
data <- read.csv (path...)
ggplot(data, aes(V2)) +
geom_histogram(alpha=0.3, fill='white', colour='black', binwidth=.04)
j'ai essayé plusieurs choses:
+ stat_function(fun=dnorm)
....n'a rien changé
+ stat_density(geom = "line", colour = "red")
...m'a donné une droite ligne rouge sur l'axe des abscisses.
+ geom_density()
ne fonctionne pas pour moi parce que je veux garder mes valeurs de fréquence sur l'axe des y, et ne veux pas de valeurs de densité.
des suggestions?
Merci à avance pour les pourboires!
Solution trouvée!
+geom_density(aes(y=0.045*..count..), colour="black", adjust=4)
4 réponses
Ce qui a été répondu ici et en partie ici.
si vous voulez que l'axe des y ait des comptes de fréquence, alors la courbe normale doit être mise à l'échelle en fonction du nombre d'observations et de la largeur de binaire.
# Simulate some data. Individuals' heights in cm.
n <- 1000
mean <- 165
sd <- 6.6
binwidth <- 2
height <- rnorm(n, mean, sd)
qplot(height, geom = "histogram", breaks = seq(130, 200, binwidth),
colour = I("black"), fill = I("white"),
xlab = "Height (cm)", ylab = "Count") +
# Create normal curve, adjusting for number of observations and binwidth
stat_function(
fun = function(x, mean, sd, n, bw){
dnorm(x = x, mean = mean, sd = sd) * n * bw
},
args = c(mean = mean, sd = sd, n = n, bw = binwidth))
EDIT
ici, créer un séparé ensemble de données contenant les données pour les courbes normales et les superposer.library(plyr)
dd <- data.frame(
predicted = rnorm(720, mean = 2, sd = 2),
state = rep(c("A", "B", "C"), each = 240)
)
binwidth <- 0.5
grid <- with(dd, seq(min(predicted), max(predicted), length = 100))
normaldens <- ddply(dd, "state", function(df) {
data.frame(
predicted = grid,
normal_curve = dnorm(grid, mean(df$predicted), sd(df$predicted)) * length(df$predicted) * binwidth
)
})
ggplot(dd, aes(predicted)) +
geom_histogram(breaks = seq(-3,10, binwidth), colour = "black", fill = "white") +
geom_line(aes(y = normal_curve), data = normaldens, colour = "red") +
facet_wrap(~ state)
Pense que je l'ai eu:
set.seed(1)
df <- data.frame(PF = 10*rnorm(1000))
ggplot(df, aes(x = PF)) +
geom_histogram(aes(y =..density..),
breaks = seq(-50, 50, by = 10),
colour = "black",
fill = "white") +
stat_function(fun = dnorm, args = list(mean = mean(df$PF), sd = sd(df$PF)))
Ceci est un commentaire étendu sur la réponse de JWilliman. J'ai trouvé la réponse de J très utile. En jouant, j'ai découvert un moyen de simplifier le code. Je ne dis pas que c'est un meilleur moyen, mais j'ai pensé le mentionner.
notez que la réponse de JWilliman fournit le compte sur l'axe des y et un "hack" pour mettre à l'échelle l'approximation de densité normale correspondante (qui autrement couvrirait une superficie totale de 1 et aurait donc un pic beaucoup plus bas).
point Principal de ce commentaire: syntaxe plus simple à l'intérieur de stat_function
, en passant les paramètres nécessaires à la fonction esthétique, par exemple
aes(x = x, mean = 0, sd = 1, binwidth = 0.3, n = 1000)
Cela évite d'avoir à passer args =
stat_function
et est donc plus convivial. Bon, c'est pas très différent, mais j'espère que quelqu'un va trouver ça intéressant.
# parameters that will be passed to ``stat_function``
n = 1000
mean = 0
sd = 1
binwidth = 0.3 # passed to geom_histogram and stat_function
set.seed(1)
df <- data.frame(x = rnorm(n, mean, sd))
ggplot(df, aes(x = x, mean = mean, sd = sd, binwidth = binwidth, n = n)) +
theme_bw() +
geom_histogram(binwidth = binwidth,
colour = "white", fill = "cornflowerblue", size = 0.1) +
stat_function(fun = function(x) dnorm(x, mean = mean, sd = sd) * n * binwidth,
color = "darkred", size = 1)
Ce code devrait le faire:
set.seed(1)
z <- rnorm(1000)
qplot(z, geom = "blank") +
geom_histogram(aes(y = ..density..)) +
stat_density(geom = "line", aes(colour = "bla")) +
stat_function(fun = dnorm, aes(x = z, colour = "blabla")) +
scale_colour_manual(name = "", values = c("red", "green"),
breaks = c("bla", "blabla"),
labels = c("kernel_est", "norm_curv")) +
theme(legend.position = "bottom", legend.direction = "horizontal")
Note: j'ai utilisé qplot mais vous pouvez utiliser le plus polyvalent ggplot.