統計学入門② データの可視化とmatplotlib

f:id:monozukuri-bu:20190513225613j:plain

浪速のPythonistこと、モノづくり部のkanaiです。

前回に引き続き、今回は様々なグラフを使ってデータの可視化を行っていきたいと思います。

Python環境

以下の環境で動作確認しています。

Python 3.7
Pandas 0.23.4

データの可視化

Matplotlib

Pythonでは、Matplotlibのpyplotモジュールを読み込むことで、
データをグラフとして描画し可視化を行うことができます。
具体的には、ヒストグラム、箱ひげ図、棒グラフ、帯グラフ、モザイク図などの様々なグラフを描画できます。

Matplotlibのpyplotはimport文で読み込めます。

import matplotlib.pyplot as plt

読み込んだ後は、pyplotにデータやグラフを設定し、show()でグラフの表示を行います。
なお、グラフをファイルとして保存したいときは、savefig()の引数にファイル名を指定すれば可能です。

それでは、実際にグラフを描画しながらどんな特徴があるのか見ていきましょう。

棒グラフ

棒グラフとは、棒状の図形で数値を表したグラフです。
前回使用したサンプルデータを棒グラフで可視化してみましょう。

# サンプルデータ
import pandas as pd

df = pd.read_csv("sample.csv")
print(df.head())
###################################################
#    生徒ID   国語   数学   理科   社会   英語
# 0  ST001     50     50     50     50     50
# 1  ST002     80     92     76     88     96
# 2  ST003     25     14     38     16     26
# 3  ST004     60     75     58     48     52
# 4  ST005    100    100     50      0      0
left = df['生徒ID']
height = df['国語']
plt.bar(left, height)
plt.show()

f:id:monozukuri-bu:20190513231513p:plain

生徒ごとの国語の点数を棒グラフで表現してみました。
数値の大小を一目で判断できるため、データの比較がしやすいですね。

データをどの順で並べるかについては特に決まりはありませんが、
用途に応じて下記のように使い分けるといいでしょう。

・データの多い順、または少ない順に並べる
・アルファベット順、または五十音順に並べる
・横軸が年や月などの時間軸である場合、時間順に並べる

帯グラフ

帯グラフは、棒グラフの長さを全て揃え、それぞれの棒の中に構成比を示したグラフです。
これによって構成比の比較がしやすくなります。

Matplotlibでは帯グラフを描画する関数が用意されていません。
そのため、今回は各データの合計値が1となるよう正規化して、
棒グラフを描画するためのモジュールを使用して帯グラフを描写する方法をとってみましょう。
ちなみに、横向きで棒グラフを描画する場合はbarh()を使用します。

例えば、A~D国に好きな色(青, 橙, 緑)のアンケートを取って結果を帯グラフで描写する実装例を紹介します。

N, K = 4, 3
data = np.random.rand(N, K)
countries = ["A", "B", "C", "D"]
favolite_colors = ["Blue", "Orange", "Green"]

# データの合計値が1となるよう正規化
normalized = data / data.sum(axis=1, keepdims=True)
cumulative = np.zeros(N)
tick = np.arange(N)

# 横向きの棒グラフを生成
for k in range(K):
    plt.barh(tick, normalized[:, k], left=cumulative, label=favolite_colors[k])
    cumulative += normalized[:, k]

plt.xlim((0, 1))
plt.yticks(tick, countries)
plt.legend()
plt.show()

f:id:monozukuri-bu:20190513230455p:plain

帯グラフは構成比をみることが目的なので、棒の長さは全て同じになります。

項目を並べる順番を途中で変えると、割合の変化がグラフを見てわからなくなってしまうので、
一つのグラフの中では順番は変えないでおきます。

ヒストグラム

ヒストグラムは、データのばらつき具合を見るのに使われます。
横軸にデータの階級を、縦軸にその階級に含まれるデータの数(例えば人数、個数など)をとって棒グラフで表します。

平均 50, 標準偏差 10 の正規乱数(正規分布に従う乱数)を1,000件生成して、結果をヒストグラムで確認してみましょう。

x = np.random.normal(50, 10, 1000) 
plt.hist(x)
plt.show()

f:id:monozukuri-bu:20190513231820p:plain

上記のヒストグラムからは、横軸45~51くらいに含まれるデータの数が一番多いことが読み取れます。
また、データがどのくらい散らばっているか(今回は標準偏差10)も視覚的にわかります。

箱ひげ図

箱ひげ図は、四角い箱の上下にひげが生えている形をしてグラフです。
箱ひげ図もサンプルデータを用いて描画してみましょう。

literature = np.array(df['国語'])
math = np.array(df['数学'])
points = (literature, math)

fig, ax = plt.subplots()
bp = ax.boxplot(points)
ax.set_xticklabels(['literature', 'math'])

plt.title('Box plot')
plt.xlabel('exams')
plt.ylabel('point')

plt.ylim([0,100])
plt.grid()

plt.show()

f:id:monozukuri-bu:20190513231837p:plain

上記の図には以下のような特徴があります。
・ひげの一番下が最小値
・箱の下部の辺が第1四分位数
・真ん中の線が第2四分位数(中央値)
・上部の辺が第3四分位数
・ひげの一番上が最大値

国語(literature)を例に挙げると、
最小値が25, 第1四分位数が50, 第2四分位数が60, 第3四分位数が80, 最大値が100となります。

複数のデータのばらつき具合を比較するのに用います。
1つのデータのばらつきを見るだけならヒストグラムでも可能ですが、
複数のデータのばらつきを比較することができるのが箱ひげ図です。

モザイク図

モザイク図は、クロス集計表の各層を縦棒の帯グラフとして表したグラフのことです。
モザイク図の横幅はカテゴリーの各層の度数の合計に比例します。

なお、モザイク図を描画するには、Pythonの統計用ライブラリのstatsmodelsが必要になります。

では、描画してみましょう。

from statsmodels.graphics.mosaicplot import mosaic
import matplotlib.pyplot as plt
 
gender = ['male', 'male', 'male', 'female', 'female', 'female', 'female', 'female']
pet = ['cat', 'dog', 'dog', 'cat', 'dog', 'cat', 'cat', 'cat']
data = pd.DataFrame({'gender': gender, 'pet': pet})
mosaic(data, ['pet', 'gender'])
plt.show()

f:id:monozukuri-bu:20190513231850p:plain

このグラフは男性と女性がそれぞれ猫と犬を何匹飼っているかを示しています。
猫が5匹、犬が3匹なので、猫の方が横幅が大きくなっています。

また、猫を飼っている女性が4人、男性が1人なので、
猫のグラフの中を見ても女性の構成比の方が大きくなっています。

その他のグラフ

pyplotを使えば、上記で紹介したグラフ以外も描写することができます。
いくつか下記に紹介してみますので、ぜひ挑戦してみてください。

グラフの種類 pyplot
折れ線 plot(x, y)
pie(x)
散布図 scatter(x, y)
バイオリン violinplot(x)

まとめ

今回は、データの可視化とそれぞれのグラフにおける特徴を学習しました。
次回は確率の考え方やScipyを使って求める方法をご紹介します。