2012-06-27 12 views
8

Jak mogę nałożyć nakładkę arbitralną na histogram przy pomocy ggplot?Jak mogę nałożyć nakładkę arbitralną na histogram przy pomocy ggplot?

Podjąłem próbę na podstawie Quick-R example, ale nie rozumiem, skąd bierze się współczynnik skalowania. Czy ta metoda jest rozsądna? Jak mogę go zmodyfikować, aby użyć ggplota?

Przykład overplot normalnych i logarytmicznie dystrybucji z wykorzystaniem tej metody, następujące:

## Get a log-normalish data set: the number of characters per word in "Alice in Wonderland" 
alice.raw <- readLines(con = "http://www.gutenberg.org/cache/epub/11/pg11.txt", 
         n = -1L, ok = TRUE, warn = TRUE, 
         encoding = "UTF-8") 

alice.long <- paste(alice.raw, collapse=" ") 
alice.long.noboilerplate <- strsplit(alice.long, split="\\*\\*\\*")[[1]][3] 
alice.words <- strsplit(alice.long.noboilerplate, "[[:space:]]+")[[1]] 
alice.nchar <- nchar(alice.words) 
alice.nchar <- alice.nchar[alice.nchar > 0] 

# Now we want to plot both the histogram and then log-normal probability dist 
require(MASS) 
h <- hist(alice.nchar, breaks=1:50, xlab="Characters in word", main="Count") 
xfit <- seq(1, 50, 0.1) 

# Plot a normal curve 
yfit<-dnorm(xfit,mean=mean(alice.nchar),sd=sd(alice.nchar)) 
yfit <- yfit * diff(h$mids[1:2]) * length(alice.nchar) 
lines(xfit, yfit, col="blue", lwd=2) 

# Now plot a log-normal curve 
params <- fitdistr(alice.nchar, densfun="lognormal") 
yfit <- dlnorm(xfit, meanlog=params$estimate[1], sdlog=params$estimate[1]) 
yfit <- yfit * diff(h$mids[1:2]) * length(alice.nchar) 
lines(xfit, yfit, col="red", lwd=2) 

to następujące Opis: Plot produced by the code above, showing a histogram of word length superimposed with a normal distribution curve and a log-normal distribution curve

celu wyjaśnienia, ja jak do zliczeń na osi y , a nie oszacowanie gęstości.

+0

pamiętać, że rozkład normalny nie ma sensu, ponieważ wszystkie słowa mają> 0 liter, a wartości są dyskretnymi liczbami całkowitymi; normalny jest ciągły. –

+0

Uzgodnione - jest to przykład zabawkowy z poręcznym zestawem danych. A normalna krzywa jest prawdopodobnie niewłaściwa. – fmark

Odpowiedz

11

Wystarczy popatrzeć na stat_function()

alice.raw <- readLines(con = "http://www.gutenberg.org/cache/epub/11/pg11.txt", 
         n = -1L, ok = TRUE, warn = TRUE, 
         encoding = "UTF-8") 

alice.long <- paste(alice.raw, collapse=" ") 
alice.long.noboilerplate <- strsplit(alice.long, split="\\*\\*\\*")[[1]][3] 
alice.words <- strsplit(alice.long.noboilerplate, "[[:space:]]+")[[1]] 
alice.nchar <- nchar(alice.words) 
alice.nchar <- alice.nchar[alice.nchar > 0] 
dataset <- data.frame(alice.nchar = alice.nchar) 
library(ggplot2) 
ggplot(dataset, aes(x = alice.nchar)) + geom_histogram(aes(y = ..density..)) + 
    stat_function(fun = dnorm, 
    args = c(
     mean = mean(dataset$alice.nchar), 
     sd = sd(dataset$alice.nchar)), 
    colour = "red") 

enter image description here

Jeśli chcesz mieć liczy na osi y, jak w przykładzie, to musisz funkcję, która przekształca gęstość do liczby:

dnorm.count <- function(x, mean = 0, sd = 1, log = FALSE, n = 1, binwidth = 1){ 
    n * binwidth * dnorm(x = x, mean = mean, sd = sd, log = log) 
} 

ggplot(dataset, aes(x = alice.nchar)) + geom_histogram(binwidth=1.6) + 
    stat_function(fun = dnorm.count, 
       args = c(
        mean = mean(dataset$alice.nchar), 
        sd = sd(dataset$alice.nchar), 
        n = nrow(dataset), binwidth=1.6), 
       colour = "red") 

enter image description here

+0

Nice. Myślę, że funkcja stat_function musi być nowa. Jest to duży postęp w stosunku do mojego poprzedniego podejścia, polegającego na stworzeniu najpierw ramki danych x, dnorm (x,,). –

+1

@David 'stat_function' jest tam tak długo, jak pamiętam! :) – joran

+0

To jest świetne - czy możliwe jest mierzenie liczby na osi Y zamiast gęstości jak w powyższym przykładzie? – fmark