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)

21
demandé sur tonytonov 2011-08-06 19:05:31

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))

Histogram with normal curve

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)
14
répondu JWilliman 2017-05-23 12:17:58

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)))

enter image description here

12
répondu Carlos Eduardo Vazquez 2017-10-22 12:21:45

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)

enter image description here

9
répondu PatrickT 2018-07-26 16:20:38

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")

enter image description here

Note: j'ai utilisé qplot mais vous pouvez utiliser le plus polyvalent ggplot.

8
répondu dickoa 2017-10-22 12:24:51