ヒストグラムはデータの分布を確認するために利用される基本的なグラフです。縦軸に度数(データの数)をとるので度数分布図とも言われます。Excelなどでヒストグラムを描くには度数分布表を作成してから描くことが多いですが、 R では元になるデータを描画関数に与えるだけでヒストグラムを描くことが可能です。
Packages and Datasets
本ページではR version 3.4.4 (2018-03-15)の標準パッケージ以外に以下の追加パッケージを用いています。
Package | Version | Description |
---|---|---|
gridExtra | 2.3 | Miscellaneous Functions for “Grid” Graphics |
tidyverse | 1.2.1 | Easily Install and Load the ‘Tidyverse’ |
また、本ページでは以下のデータセットを用いています。
Dataset | Package | Version | Description |
---|---|---|---|
iris | datasets | 3.4.4 | Edgar Anderson’s Iris Data |
mtcars | datasets | 3.4.4 | Motor Trend Car Road Tests |
diamonds | ggplot2 | 3.1.0 | Prices of 50,000 round cut diamonds |
ヒストグラムを描くのに必要な情報
ヒストグラムを描くためには階級(ビン)を正しく指定する方法があります。
基本的な考え方
階級(ビン)を決める一意の方法はありません。階級の幅(ビンの幅)が異なるとヒストグラムの形状も異なるためにデータの特徴を最も表せるような階級の幅(ビンの幅)を定める必要があります。ただし、既に様々な計算方法が提案されていますのでこれらを有効に使ってください。
階級数の求め方
階級を決めるには階級の数(ビンの個数)または階級の幅(ビンの幅)を決める必要があります。階級の幅(ビンの幅)は階級の数(ビンの個数)を元に決めることができ、階級の数(ビンの個数)を求めるのに下表のような計算方法があります。具体的な計算方法はネットなどで確認してください。
階級数の計算方法 | Rでの関数 | 備考 |
---|---|---|
Square-root choice | sqrt(length(x)) |
データxの数(n)の平方根 |
Sturges’s formula | nclass.Sturges(x) |
データxの数(n)が\(n \ge 30\)を満たす場合 |
Scott’s choice | nclass.scott(x) |
標準偏差を用いる計算方法 |
Freedman-Diaconis choice | nclass.FD(x) |
四分位範囲に基づく計算方法 |
実際に以下のmtcars
データセットのmpg
とdisp
、hp
各データの階級の数(ビンの個数)がどのような値になるか比較してみます。
mtcars
## # A tibble: 32 x 11
## mpg cyl disp hp drat wt qsec vs am gear carb
## * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
## 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
## 3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
## 4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
## 5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
## 6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
## 7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
## 8 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
## 9 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
## 10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
## # ... with 22 more rows
階級数の計算方法 | mpgの階級数 | dispの階級数 | hpの階級数 |
---|---|---|---|
Square-root choice | 6 | 6 | 6 |
Sturges’s formula | 6 | 6 | 6 |
Scott’s choice | 4 | 3 | 4 |
Freedman-Diaconis choice | 6 | 4 | 6 |
このように計算方法により階級の数(ビンの個数)が異なることが分かります。
階級(幅)の求め方
階級数が求められましたので次に階級(幅)を求めます。対象となるデータの範囲を単に階級数で割ると中途半端な階級幅になってしまうことがありますので、R では適切な階級(幅)を得るためのpretty
関数が用意されていますのでこれを使います。
pretty(x, n)
pretty
関数は\(x\)の値の範囲をカバーし(階級数+1)個となるような階級を計算します。ただし、適切な階級になるように調整1が行われます。
1 The values are chosen so that they are 1, 2 or 5 times a power of 10.
実際にpretty
関数を用いてmpg
とdisp
、hp
各データに対する階級を計算してみます。
mpgの階級数と階級
階級数の計算方法 | 階級数 | 階級 |
---|---|---|
Square-root choice | 6 | 10, 15, 20, 25, 30, 35 |
Sturges’s formula | 6 | 10, 15, 20, 25, 30, 35 |
Scott’s choice | 4 | 10, 15, 20, 25, 30, 35 |
Freedman-Diaconis choice | 6 | 10, 15, 20, 25, 30, 35 |
dispの階級数と階級
階級数の計算方法 | 階級数 | 階級 |
---|---|---|
Square-root choice | 6 | 50, 100, 150, 200, 250, 300, 350, 400, 450, 500 |
Sturges’s formula | 6 | 50, 100, 150, 200, 250, 300, 350, 400, 450, 500 |
Scott’s choice | 3 | 0, 100, 200, 300, 400, 500 |
Freedman-Diaconis choice | 4 | 0, 100, 200, 300, 400, 500 |
hpの階級数と階級
階級数の計算方法 | 階級数 | 階級 |
---|---|---|
Square-root choice | 6 | 50, 100, 150, 200, 250, 300, 350 |
Sturges’s formula | 6 | 50, 100, 150, 200, 250, 300, 350 |
Scott’s choice | 4 | 0, 100, 200, 300, 400 |
Freedman-Diaconis choice | 6 | 50, 100, 150, 200, 250, 300, 350 |
これで階級が求められました。
度数分布表
ヒストグラムを描く前に求めた階級から度数分布表を作成してみましょう。データがどの階級に含まれるかを求めるにはcut
関数を使います。度数はcut
関数で求めた階級をdplyr::count
関数で集計することで簡単に求められます。
dispの度数分布表
Square-root choice & Sturges’s formula
x <- mtcars$disp # 対象データ
n <- round(sqrt(length(x))) # 階級数を求める
breaks <- pretty(x, n) # 階級を求める
mtcars %>%
dplyr::mutate(freq = cut(disp, breaks = breaks, include.lowest = TRUE)) %>%
dplyr::count(freq) %>%
dplyr::mutate(cum = cumsum(n)) %>%
dplyr::rename(`階級` = freq, `度数` = n, `累積度数` = cum)
## # A tibble: 9 x 3
## 階級 度数 累積度数
## <fct> <int> <int>
## 1 [50,100] 5 5
## 2 (100,150] 7 12
## 3 (150,200] 4 16
## 4 (200,250] 1 17
## 5 (250,300] 4 21
## 6 (300,350] 4 25
## 7 (350,400] 4 29
## 8 (400,450] 1 30
## 9 (450,500] 2 32
Scott’s choice & Freedman-Diaconis choice
x <- mtcars$disp # 対象データ
n <- nclass.scott(x) # 階級数を求める
breaks <- pretty(x, n) # 階級を求める
mtcars %>%
dplyr::mutate(freq = cut(disp, breaks = breaks, include.lowest = TRUE)) %>%
dplyr::count(freq) %>%
dplyr::mutate(cum = cumsum(n)) %>%
dplyr::rename(`階級` = freq, `度数` = n, `累積度数` = cum)
## # A tibble: 5 x 3
## 階級 度数 累積度数
## <fct> <int> <int>
## 1 [0,100] 5 5
## 2 (100,200] 11 16
## 3 (200,300] 5 21
## 4 (300,400] 8 29
## 5 (400,500] 3 32
ヒストグラム
標準パッケージを用いる方法
標準パッケージにはhist
関数というヒストグラム描画用関数が用意されています。hist
関数はデフォルトでSturgesの公式を用いた階級を元にヒストグラムを描画します。
dispのヒストグラム
x <- mtcars$disp
old_par <- par()
op <- par(mfrow = c(2, 2))
hist(x, breaks = pretty(x, round(sqrt(length(x)))), main = "Square-root choice")
hist(x, main = "Sturges's formula (default)")
hist(x, breaks = "scott", main = "Scott's choice")
hist(x, breaks = "FD", main = "Freedman-Diaconis choice")
par(op)
par(old_par)
追加パッケージを用いる方法
ggplot2
パッケージにはggplot2::geom_histgram
関数というヒストグラム描画用関数が用意されています。ggplot2::geom_histgram
関数はhist
関数とは異なりデフォルトで単純分割の階級幅(階級数=30)を取りますので階級幅は別途指定することを推奨します。
dispのヒストグラム
x <- mtcars$disp
gg_def <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram() +
ggplot2::labs(title = "Default", x = "", y = "")
n <- nclass.Sturges(x)
gg_sf <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = pretty(x, n)) +
ggplot2::labs(title = "Square-root choice & Sturges's formula", x = "", y = "")
n <- nclass.scott(x)
gg_sc <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = pretty(x, n)) +
ggplot2::labs(title = "Scott's choice", x = "", y = "")
n <- nclass.FD(x)
gg_fdc <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = pretty(x, n)) +
ggplot2::labs(title = "Freedman-Diaconis choice", x = "", y = "")
gridExtra::grid.arrange(gg_def, gg_sf, gg_sc, gg_fdc)
任意の階級を指定する
データによってはSturgesの公式などから求めた階級でも適切な階級にならない場合があります。ggplot2
パッケージに含まれるdiamonds
データセットを例にして任意の階級の指定方法を示します。
diamonds
データセットは5万個を超えるダイヤモンドに関するデータです。ダイアモンドの重さ(カラット数)の五数要約(0.2, 0.4, 0.7, 1.04, 5.01)を見る限り右に歪んだロングテールな分布になっていることが想像できます。前出の4つの計算式を用いてdiamonds
データセットの階級数と階級幅を求めてみます。
階級数の計算方法 | 階級数 | 階級幅 |
---|---|---|
Square-root choice | 232 | 0.02 |
Sturges’s formula | 17 | 0.5 |
Scott’s choice | 110 | 0.05 |
Freedman-Diaconis choice | 142 | 0.05 |
これを元にヒストグラムを描いてみます。
n <- round(sqrt(length(x)))
gg_src <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = pretty(x, n)) +
ggplot2::labs(title = "Square-root choice", x = "", y = "")
n <- nclass.Sturges(x)
gg_sf <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = pretty(x, n)) +
ggplot2::labs(title = "Sturges's formula", x = "", y = "")
n <- nclass.scott(x)
gg_sc <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = pretty(x, n)) +
ggplot2::labs(title = "Scott's choice", x = "", y = "")
n <- nclass.FD(x)
gg_fdc <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = pretty(x, n)) +
ggplot2::labs(title = "Freedman-Diaconis choice", x = "", y = "")
gridExtra::grid.arrange(gg_src, gg_sf, gg_sc, gg_fdc)
グラフを見て分かるようにSquare-root choiceは階級幅が狭すぎるように見えます。また、Sturgesの公式は階級幅が広すぎてデータが集中している部分が埋もれてしまっています。Scottの選択やFreedman-Diaconisの選択は前述の二つに比べると形状が見えていますが階級幅が狭いように感じます。
このような場合は公式などを利用せずに任意の階級を指定することで適切なヒストグラムを描くことが可能です。例えば、階級幅を0.1カラット単位にすると下図のようになります。
breaks <- c(seq(0, 5.0, 0.1))
gg_any <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = breaks) +
ggplot2::labs(title = "任意の階級幅指定[0.1 carat]", x = "", y = "")
gridExtra::grid.arrange(gg_sc, gg_any, ncol = 2)
階級幅を0.2カラット単位にすると下図のようになり1カラット近辺にも大きなピークがあることが見えてきます。
breaks <- c(seq(0, 5.0, 0.2))
gg_any2 <- as.data.frame(x) %>%
ggplot2::ggplot(aes(x = x)) +
ggplot2::geom_histogram(breaks = breaks) +
ggplot2::labs(title = "任意の階級幅指定[0.2 carat]", x = "", y = "")
gridExtra::grid.arrange(gg_sc, gg_any, gg_any2, ncol = 2)
左閉じと右閉じ
ヒストグラムの形状に影響を与えるのは階級だけではありません。度数の集計条件もヒストグラムの形状に大きな影響を与えます。集計条件には下表のように二つの条件があります。
集計条件 | 内容 |
---|---|
階級の閉じ | 階級の下端値と上端値のどちらを含めるか(下表参照) |
階級最下限値 | 最も下側の階級の下端値を含めるか否か |
階級の閉じ | 集計条件 | 表記 | 備考 |
---|---|---|---|
左閉じ | \(a \le 階級 \lt b\) | [a, b) | a以上b未満を階級内とする |
右閉じ | \(a \lt 階級 \le b\) | (a, b] | aを超えb以下を階級内とする |
両閉じ | \(a \le 階級 \le b\) | [a, b] | 最下限の階級のみに適用される |
mtcars
データセットのhp
データで階級の閉じを変えた場合のヒストグラムを以下に示します。
gg_left <- mtcars %>%
ggplot2::ggplot(aes(x = hp)) +
ggplot2::geom_histogram(breaks = pretty(mtcars$hp,
n = nclass.Sturges(mtcars$hp)),
closed = "left") +
ggplot2::labs(title = "左閉じ", y = "")
gg_right <- mtcars %>%
ggplot2::ggplot(aes(x = hp)) +
ggplot2::geom_histogram(breaks = pretty(mtcars$hp,
n = nclass.Sturges(mtcars$hp)),
closed = "right") +
ggplot2::labs(title = "右閉じ(default)", y = "")
gridExtra::grid.arrange(gg_left, gg_right, ncol = 2)
このように度数分布の集計条件を変るとヒストグラム形状も変わる場合がありますので注意してください。なお、hist
関数、ggplot2::geom_histgram
関数共に階級の閉じは「右閉じ」がデフォルトになっています。