Добавяне на линия на плътност към хистограма с данни за броя в 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)

РЕДАКТИРАНЕ: Отговор на коментара на OP.

Коефициентът на мащаба е binwidth ✕ размер на извадката.

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)) не може да се обобщи за различни bin-widths или размери на извадката. Да предположим, че имам размер на извадката 2474 (вместо 10 000) и 0,03 (вместо 0,01). Вярвам, че 0,01 трябва да бъде функцията на ширината на контейнера и евентуално размера на извадката. - person HBat; 27.12.2014
comment
Абсолютно е обобщаващо. 0.01 е binwidth. Така че, ако използвате 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