のグループ化されたヒストグラムに正規分布の適合を重ね合わせるための最もエレガントな方法を探していggplot2
ます。私はこの質問をする前に何度も頼まれていますが、のような提案の選択肢のどれも、知っているこのいずれかまたはこの1つはない限り、非常にエレガントとして私を打たない、少なくともないstat_function
データの各特定のサブセクション上で動作するように作ることができます。
私が遭遇したグループ化されていないヒストグラムに正規分布の適合を重ね合わせるための比較的洗練された方法の1つは、geom_smooth
andを使用method="nls"
することでした(それは自己開始関数ではなく、開始値を指定する必要があるという事実は別として):
library(ggplot2)
myhist = data.frame(size = 10:27, counts = c(1L, 3L, 5L, 6L, 9L, 14L, 13L, 23L, 31L, 40L, 42L, 22L, 14L, 7L, 4L, 2L, 2L, 1L) )
ggplot(data=myhist, aes(x=size, y=counts)) + geom_point() +
geom_smooth(method="nls", formula = y ~ N * dnorm(x, m, s), se=F,
start=list(m=20, s=5, N=300))
このアプローチを使用して、グループ化されたヒストグラムに正規分布の近似を追加することもできるかどうか疑問に思いました。
library(devtools)
install_github("tomwenseleers/easyGgplot2",type="source")
library("easyGgplot2") # load weight data
ggplot(weight,aes(x = weight)) +
+ geom_histogram(aes(y = ..count.., colour=sex, fill=sex),alpha=0.5,position="identity")
私はまた、万が一(グループ化の可能性がある)のために+ stat_distrfit()
または+ stat_normfit(
)を定義する可能性のあるパッケージがあるかどうか疑問に思っていましたかggplot2
?(私は実際には何も見つけることができませんでしたが、これは十分に一般的なタスクのように思われるので、私はただ疑問に思っていました)
コードをできるだけ短くしたい理由は、これがコース用であり、物事をできるだけ簡単に保ちたいからです...
PS geom_density
does not suit my goal and I would also like to plot the counts/frequencies as opposed to the density. I would also like to have them in the same panel, and avoid using facet_wrap
Like this?
## simulate your dataset - could not get easyGplot2 to load....
set.seed(1) # for reproducible example
weight <- data.frame(sex=c("Female","Male"), weight=rnorm(1000,mean=c(65,67),sd=1))
library(ggplot2)
library(MASS) # for fitdistr(...)
get.params <- function(z) with(fitdistr(z,"normal"),estimate[1:2])
df <- aggregate(weight~sex, weight, get.params)
df <- data.frame(sex=df[,1],df[,2])
x <- with(weight, seq(min(weight),max(weight),len=100))
gg <- data.frame(weight=rep(x,nrow(df)),df)
gg$y <- with(gg,dnorm(x,mean,sd))
gg$y <- gg$y * aggregate(weight~sex, weight,length)$weight * diff(range(weight$weight))/30
ggplot(weight,aes(x = weight, colour=sex)) +
geom_histogram(aes(y = ..count.., fill=sex), alpha=0.5,position="identity") +
geom_line(data=gg, aes(y=y))
I suppose "elegant" is in the eye of the beholder. The problem with using stat_function(...)
is that the args=...
list cannot be mapped using aes(...)
, as the post in the comments explains. So you have to create an auxiliary data.frame (gg
in this example) that has the x- and y-values for the fitted distributions, and use geom_line(...)
.
上記のコードfitdistr(...)
は、MASS
パッケージで使用して、正規性の仮定に基づいて、性別ごとにグループ化されたデータの平均とsdの最尤推定値を計算します(意味がある場合は、別の分布を使用できます)。次に、範囲weight
を100の増分に分割して、x軸を作成dnorm(x,...)
し、適切な平均とsdを計算します。結果は密度であるため、次を使用して調整する必要があります。
gg$y <- gg$y * aggregate(weight~sex, weight,length)$weight * diff(range(weight$weight))/30
これをカウントデータに対してマッピングしたいからです。これは、geom_histogramのデフォルトのビニング(xの範囲を30の等しい増分に分割する)を使用することを前提としていることに注意してください。最後に、レイヤー固有のデータセットとしてgeom_line(...)
usingへの呼び出しを追加しますgg
。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加