ポアソン分布より分散が大きい分布としての負の二項分布
基礎
ポアソン分布はカウントデータ(非負の整数のデータ)に対する基本的な分布で、平均と分散が等しい性質があります。
一方、現実のデータ分析では平均より分散が大きいケースがよくあり、そのような状況を過分散(overdispersion)と呼んだりします。
過分散に対応するため、ポアソン分布の代わりに負の二項分布が使われることがあります。
このことはパラメータがガンマ分布に従って変化するようなポアソン分布が負の二項分布になることを知ると理解しやすいです。
ポアソン分布のパラメータを
すなわち、次のようなデータ生成過程を考えます。
ここではガンマ分布の2つのパラメータをどちらも同じ
ガンマ関数の定義が
これは負の二項分布
統計ソフト R の負の二項分布関連の関数(dnbinom
、pnbinom
、qnbinom
、rnbinom
) では size
という引数、 mu
という引数で指定します。
念のため、ガンマ分布のレート(スケールの逆数)パラメータが自由に動くときも考えておきます。
ガンマ分布のレートパラメータを
R によるケーススタディ
統計局ホームページ)/第六十三回日本統計年鑑 平成26年−第2章 人口・世帯 の「2 - 5 都道府県別人口集中地区人口,面積及び人口密度(エクセル:34KB)」 を使い、人口の分布を調べます。
library(dplyr)
library(ggplot2)
library(readxl)
library(ggrepel)
dat <-read_xls("~/Downloads/y0205000.xls",skip=8) %>%
slice(-c(1:8)) %>%
select('...1', '人口...3','面積...4') %>%
setNames(c("pref","pop","area")) %>%
dplyr::filter(!is.na(pop)) %>%
mutate(pop=as.integer(pop),area=as.numeric(area)) %>%
mutate(pref=gsub("^[0-9][0-9] ", "", pref))
まずポアソン分布を用いたモデルを考え、「面積あたりの人口」をパラメータとします。
すなわち、次のような確率分布を考えます。
ここで
最尤推定量は次のように得られます(証明略)。
lambahat <- sum(dat$pop)/sum(dat$area)
最尤推定されたパラメータを持つ分布から1万回乱数の抽出をおこない、分布の95%区間をプロットしてみます。
set.seed(1234)
sim1 <-matrix(rpois(10000*47,dat$area*lambahat),47,10000)
int1 <-as.data.frame(t(apply(sim1,1,quantile,prob=c(0.025,0.975)))) %>%
setNames(c("lower","upper")) %>%
mutate(area=dat$area)
ggplot(dat,aes(x=area))+
geom_point(aes(y=pop))+
geom_ribbon(data=int1,aes(ymin=lower,ymax=upper),alpha=0.3)+
theme_bw(16)
縦軸が人工、横軸が面積です。
平均はだいたい捉えていますが、データの散らばり具合をカバーしきれていないことがわかります。
次に負の二項分布を用いて、
なるモデルを考えます。
最尤推定は最適化関数の optim
に丸投げします。
ll <- function(par,y,tau){
sum(dnbinom(y,size = exp(par[1]), mu = exp(par[2]+tau), log = TRUE))
}
opt <-optim(c(0,0),ll,y=dat$pop,tau=log(dat$area),control = list(fnscale=-1))
こちらも最尤推定されたパラメータを持つ分布から1万回乱数の抽出をおこない、分布の95%区間をプロットしてみます。
前半の考察を確かめるため、ガンマ分布にしたがってパラメータが変化するポアソン分布を愚直に書いています。
r <- rgamma(10000*47,exp(opt$par[1]),exp(opt$par[1]))
sim2 <-matrix(rpois(10000*47,dat$area*r*exp(opt$par[2])),47,10000)
int2 <-as.data.frame(t(apply(sim2,1,quantile,prob=c(0.025,0.975)))) %>%
setNames(c("lower","upper")) %>%
mutate(area=dat$area)
subdat <- dat[dat$pop > int2$upper,]
ggplot(dat,aes(x=area))+
geom_point(aes(y=pop))+
geom_ribbon(data=int2,aes(ymin=lower,ymax=upper),alpha=0.3)+
geom_text_repel(data = subdat , aes(y=pop, label = pref), family="Osaka")+
theme_bw(16)
データの散らばり具合に近い分布が推定されていることがわかります。
Discussion