Добавление линии плотности к гистограмме с данными подсчета в ggplot2

Я хочу добавить линию плотности (на самом деле, нормальную плотность) к гистограмме.

Предположим, у меня есть следующие данные. Я могу построить гистограмму с помощью ggplot2:

set.seed(123)    
df <- data.frame(x = rbeta(10000, shape1 = 2, shape2 = 4))

ggplot(df, aes(x = x)) + geom_histogram(colour = "black", fill = "white", 
                                        binwidth = 0.01) 

введите здесь описание изображения

Я могу добавить линию плотности, используя:

ggplot(df, aes(x = x)) + 
  geom_histogram(aes(y = ..density..),colour = "black", fill = "white", 
                 binwidth = 0.01) + 
  stat_function(fun = dnorm, args = list(mean = mean(df$x), sd = sd(df$x)))

введите здесь описание изображения

Но это не то, чего я на самом деле хочу, я хочу, чтобы эта линия плотности соответствовала данным подсчета.

Я нашел похожий пост (ЗДЕСЬ), который предложил решение этой проблемы. Но в моем случае это не сработало. Мне нужен произвольный коэффициент расширения, чтобы получить то, что я хочу. И это вообще не обобщается:

ef <- 100 # Expansion factor

ggplot(df, aes(x = x)) + 
  geom_histogram(colour = "black", fill = "white", binwidth = 0.01) + 
  stat_function(fun = function(x, mean, sd, n){ 
    n * dnorm(x = x, mean = mean, sd = sd)}, 
    args = list(mean = mean(df$x), sd = sd(df$x), n = ef))

введите здесь описание изображения

Любые подсказки, которые я могу использовать, чтобы обобщить это

  • сначала к нормальному распределению,
  • затем к любому другому размеру корзины,
  • и, наконец, для любого другого дистрибутива будет очень полезно.

person HBat    schedule 26.12.2014    source источник
comment
Вы имели в виду, что два изображения диаграммы должны быть одинаковыми? Похоже, вы дважды загрузили один и тот же файл.   -  person arvi1000    schedule 27.12.2014
comment
Используйте fitdistr(...) в пакете MASS, чтобы соответствовать дистрибутивам.   -  person jlhoward    schedule 27.12.2014


Ответы (1)


Подгонка функции распределения не происходит по волшебству. Вы должны сделать это явно. Один из способов — использовать fitdistr(...) в пакете MASS.

library(MASS)    # for fitsidtr(...)
# excellent fit (of course...)
ggplot(df, aes(x = x)) + 
  geom_histogram(aes(y=..density..),colour = "black", fill = "white", binwidth = 0.01)+
  stat_function(fun=dbeta,args=fitdistr(df$x,"beta",start=list(shape1=1,shape2=1))$estimate)

# horrible fit - no surprise here
ggplot(df, aes(x = x)) + 
  geom_histogram(aes(y=..density..),colour = "black", fill = "white", binwidth = 0.01)+
  stat_function(fun=dnorm,args=fitdistr(df$x,"normal")$estimate)

# mediocre fit - also not surprising...
ggplot(df, aes(x = x)) + 
  geom_histogram(aes(y=..density..),colour = "black", fill = "white", binwidth = 0.01)+
  stat_function(fun=dgamma,args=fitdistr(df$x,"gamma")$estimate)

EDIT: ответ на комментарий OP.

Масштабный коэффициент равен ширине бина ✕ размеру выборки.

ggplot(df, aes(x = x)) + 
  geom_histogram(colour = "black", fill = "white", binwidth = 0.01)+
  stat_function(fun=function(x,shape1,shape2)0.01*nrow(df)*dbeta(x,shape1,shape2),
                args=fitdistr(df$x,"beta",start=list(shape1=1,shape2=1))$estimate)

person jlhoward    schedule 26.12.2014
comment
Спасибо за обобщение на разные дистрибутивы. Моя конечная цель состоит в том, чтобы подогнать эти линии к данным подсчета, а не к плотности. Есть ли у вас какие-либо идеи о том, как это сделать? (Я хочу получить тот же сюжет, что и третий сюжет исходного поста.) - person HBat; 27.12.2014
comment
Значение 0.01 в формуле (0.01*nrow(df)*dbeta(x,shape1,shape2)) нельзя обобщить на разные ширины ячеек или размеры выборки. Предположим, у меня размер выборки 2474 (вместо 10000) и 0,03 (вместо 0,01). Я считаю, что 0,01 должно быть функцией ширины ячейки и, возможно, размера выборки. - person HBat; 27.12.2014
comment
Это абсолютно можно обобщить. 0.01 - это ширина бина. Итак, если вы используете binwidth=0.03, то вы должны использовать fun=function(x,shape1,shape2)0.03*nrow(df)*dbeta(x,shape1,shape2) в вызове stat_function(...). Конечно, все показатели изменились бы. - person jlhoward; 27.12.2014
comment
Моя ошибка, это можно обобщить на разные размеры бинов и размеры выборки. Спасибо за решение. - person HBat; 27.12.2014