2011-08-06 37 views
17

que he estado tratando de superponer una curva normal por encima de mi histograma con ggplot 2.ggplot2: Histograma con la curva normal

Mi fórmula:

data <- read.csv (path...) 

ggplot(data, aes(V2)) + 
    geom_histogram(alpha=0.3, fill='white', colour='black', binwidth=.04) 

He intentado varias cosas:

+ stat_function(fun=dnorm) 

.... no cambió nada

+ stat_density(geom = "line", colour = "red") 

... me dio una línea roja recta en el eje x.

+ geom_density() 

no funciona para mí porque quiero mantener mis valores de frecuencia en el eje y, y quiero no hay valores de densidad.

¿Alguna sugerencia?

¡Gracias de antemano por cualquier consejo!

¡Solución encontrada!

+geom_density(aes(y=0.045*..count..), colour="black", adjust=4)

+0

cheque esta respuesta mía sobre una cuestión relacionada, donde he escrito una función genérica para superponer histograma en parcela densidad. http://stackoverflow.com/questions/6847450/r-how-to-plot-gumbel-distribution-using-ggplot2s-stat-function/6848958#6848958 – Ramnath

+0

Pero esa función requiere valores de densidad en el eje y, ¿verdad? ¡Deseo mantener mis recuentos de frecuencia allí! No quiero una gráfica de densidad, sino una curva normal simple. – Bloomy

+0

pero la curva normal tiene densidades. entonces estoy confundido quieres una curva normal con conteos de frecuencia? – Ramnath

Respuesta

7

Este código debe hacerlo:

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

Nota: He utilizado qplot pero se puede utilizar el ggplot más versátil.

+1

Esto no es exactamente lo que estoy buscando porque me da valores de densidad en el eje y y quiero mantener mis recuentos de frecuencia allí. – Bloomy

+2

Veo, pero ¿cuál es la diferencia "real" entre frecuencia y densidad, después de todo no es la misma información ... además es mucho más fácil con la densidad debido a la definición del PDF. – dickoa

10

que lo tengo:

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

+2

Bienvenido a Stack Overflow, ¿puede elaborar más su respuesta? –

+3

Es mejor usar 'ggsave()' - menos código y menos propenso a errores. – MERose

+0

Captura de pantalla agregada + datos agregados (según la respuesta de dickoa) para que se pueda ejecutar el código. También se eliminó la parte de guardado de la trama, ya que es una distracción. Puede revertir los cambios de curso. – PatrickT

12

Esto ha sido contestada here y parcialmente here.

Si desea que el eje y tenga recuentos de frecuencia, entonces la curva normal debe escalarse de acuerdo con el número de observaciones y el ancho de la ranura.

# 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

EDITAR

O, para un enfoque más flexible que permite el uso de facetas y se basa en un enfoque que aparece here, crear un conjunto de datos independiente que contiene los datos para las curvas normales y superponer estos.

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

Este es un comentario extendido sobre la respuesta de JWilliman. Encontré la respuesta de J muy útil. Mientras jugaba descubrí una forma de simplificar el código. No digo que sea una mejor manera, pero pensé que lo mencionaría. Si hay inconvenientes de tipo "R infierno", eliminaré este comentario extendido como se recomienda.

Observe que la respuesta de JWilliman proporciona el recuento del eje y y un "truco" para escalar la aproximación normal de densidad correspondiente (que de lo contrario cubriría un área total de 1 y por lo tanto tendría un pico mucho más bajo).

Punto principal de este comentario: sintaxis simple dentro de stat_function, pasando los parámetros necesarios a la función estética, p.

aes(x = x, mean = 0, sd = 1, binwidth = 0.3, n = 1000)

Esto evita tener que pasar args =-stat_function y por lo tanto es más fácil de usar. De acuerdo, no es muy diferente, pero con suerte alguien lo encontrará interesante.

# 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

+0

Creo que es una característica novedosa en '' ggplot2'' poder pasar estos parámetros a '' aes() '' sin tenerlos dentro del marco de datos. Podría estar equivocado. – PatrickT

Cuestiones relacionadas