2011-08-06 14 views
17

Próbowałem nałożyć normalną krzywą nad moim histogramu z ggplot 2.ggplot2: histogramu z krzywą normalną

mój wzór:

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

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

Próbowałem kilka rzeczy:

+ stat_function(fun=dnorm) 

.... nic nie zmieniło

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

... dał mi prostą czerwoną linię na osi X.

nie działa dla mnie, ponieważ chcę zachować moje wartości częstotliwości na osi Y i nie chcę żadnych wartości gęstości.

Wszelkie sugestie?

Z góry dziękuję za wszelkie wskazówki!

Rozwiązanie znalezione!

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

+0

check to odpowiedź na moje pytanie powiązanym, gdzie pisałem rodzajowe funkcji nałożyć histogram na działce gęstości. http://stackoverflow.com/questions/6847450/r-how-to-plot-gumbel-distribution-using-ggplot2s-stat-function/6848958#6848958 – Ramnath

+0

Ale ta funkcja wymaga wartości gęstości na osi Y, prawda? Chcę mieć tam swoją częstotliwość! Nie chcę wykresu gęstości, ale prostej krzywej normalnej. – Bloomy

+0

, ale krzywa normalna ma gęstości. więc jestem zdezorientowany. chcesz normalną krzywą z licznością częstotliwości? – Ramnath

Odpowiedz

7

Ten kod powinien zrobić:

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

Uwaga: Kiedyś qplot ale można użyć bardziej wszechstronny ggplot.

+1

Nie jest to dokładnie to, czego szukam, ponieważ daje mi wartości gęstości na osi Y i chcę utrzymać tam swoją częstotliwość! – Bloomy

+2

Rozumiem, ale jaka jest "rzeczywista" różnica między częstotliwością i gęstością, to nie jest ta sama informacja ... a ponadto gęstość jest o wiele łatwiejsza z powodu definicji pliku PDF. – dickoa

10

że mam go:

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

Witamy w Stack Overflow, czy możesz bardziej rozwinąć swoją odpowiedź? –

+3

Lepiej używać 'ggsave()' - mniej kodu i mniej podatnych na błędy. – MERose

+0

Dodano zrzut ekranu + dodane dane (na podstawie odpowiedzi dickoa), aby kod mógł zostać uruchomiony. Usunięto również część oszczędzającą fabułę, ponieważ jest to rozproszenie. Możesz wycofać zmiany kursu. – PatrickT

12

Zostało odpowiedział here i częściowo here.

Jeśli chcesz, aby oś Y miała zliczenia częstotliwości, wówczas normalna krzywa musi zostać przeskalowana zgodnie z liczbą obserwacji i pojemnością binarki.

# 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

albo, bardziej elastyczne podejście pozwala na wykorzystanie ścianek i opiera podejścia wymienionych here utworzyć oddzielny zbiór danych zawierający dane normalne krzywe i nałożyć te.

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

To jest rozszerzony komentarz na temat odpowiedzi JWillimana. Uważam, że odpowiedź J jest bardzo przydatna. Podczas zabawy odkryłem sposób na uproszczenie kodu. Nie mówię, że to lepszy sposób, ale pomyślałem, że o tym wspomnę. Jeśli istnieją wady typu "R's Hell", usuniemy ten rozszerzony komentarz zgodnie z zaleceniami.

Należy zauważyć, że odpowiedź JWillimana podaje liczbę na osi Y i "hakowanie" w celu skalowania odpowiadającej gęstości normalnego przybliżenia (które w przeciwnym razie obejmowałoby całkowitą powierzchnię 1, a zatem miałoby znacznie niższy pik).

Główny punkt tego komentarza: prostsza składnia wewnątrz stat_function, przekazując potrzebne parametry do funkcji estetycznej, np.

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

ten unika konieczności przechodzenia args = do stat_function i dlatego jest bardziej przyjazny dla użytkownika. Okay, to nie jest inaczej, ale mam nadzieję, że ktoś uzna to za interesujące.

# 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

Myślę, że jest to nowa funkcja w '' ggplot2'', która może przekazywać te parametry do '' aes() '', ale nie ma ich w ramce danych. Mogę się mylić. – PatrickT