データサイエンス入門:データの理解と可視化
データ分析プロジェクトにおいて、最初の重要なステップの一つは、手元にあるデータを深く理解することです。データがどのような特徴を持っているのか、変数間にはどのような関係があるのかを把握しなければ、適切な分析手法を選択したり、意味のある洞察を得たりすることは困難です。
この講義では、データ理解の基本的な手法である記述統計量の確認とデータの可視化に焦点を当てます。特に、Pythonのライブラリ(pandas
, matplotlib
, seaborn
)を Google Colaboratory 上で使用し、gapminder
データセットを使って代表的なグラフを作成する方法を学びます。
本日の学習目標:
- データセットの基本的な情報を把握する(記述統計量、データ型など)。
- 目的別に適切なグラフを選択し、作成できるようになる。
- 散布図 (Scatterplot)
- 折れ線グラフ (Linegraph)
- ヒストグラム (Histogram)
- 箱ひげ図 (Boxplot)
- 棒グラフ (Barplot)
- 作成したグラフからデータの傾向やパターンを読み取る基本的な視点を養う。
使用ツール:
- Google Colaboratory (Colab): クラウドベースの Python 実行環境
- Python: プログラミング言語
- ライブラリ:
gapminder
: データセットを提供pandas
: データ操作・分析の基本ライブラリmatplotlib
: グラフ描画ライブラリseaborn
:matplotlib
をベースにした、より美しいグラフを簡単に描画できるライブラリ
- スライド:
1. 環境設定とデータの準備
まず、Google Colab で新しいノートブックを開き、必要なライブラリをインストール・インポートします。
# Gapminder データセットをインストール
!pip install gapminder
# 必要なライブラリをインポート
import pandas as pd
from gapminder import gapminder # データセット本体
import matplotlib.pyplot as plt
import seaborn as sns
# 日本語表示のための設定(オプション)
!pip install japanize-matplotlib
import japanize_matplotlib
# Seaborn のスタイル設定(見やすいように)
sns.set_style('darkgrid')
次に、gapminder
データセットを pandas
の DataFrame として読み込みます。
# データの読み込み
df = gapminder
2. データのサマリー把握
グラフを作成する前に、データセットの基本的な情報を確認しましょう。
最初の数行を表示 (head()
):
# データの最初の5行を表示
print("--- データの一部 (最初の5行) ---")
print(df.head())
データの基本情報 (info()
): 各列のデータ型や欠損値の有無を確認します。
# データフレームの情報を表示
print("\n--- データフレームの情報 ---")
df.info()
- RangeIndex: データの行数 (1704行)
- Data columns: 列数 (6列)
- Non-Null Count: 各列に欠損値がないことがわかります。
- Dtype: 各列のデータ型(
object
は文字列、int64
は整数、float64
は浮動小数点数)。
記述統計量 (describe()
): 数値データ列の基本的な統計量(件数、平均、標準偏差、最小値、四分位数、最大値)を表示します。
# 数値列の記述統計量を表示
print("\n--- 数値列の記述統計量 ---")
print(df.describe())
year
(年)、pop
(人口)、lifeExp
(平均寿命)、gdpPercap
(一人あたりGDP)の統計量が確認できます。- 例えば、平均寿命 (
lifeExp
) は最小約23.6歳から最大約82.6歳まで、かなり幅があることがわかります。
カテゴリ変数の確認 (value_counts()
): カテゴリデータ(ここでは continent
と country
)に含まれる項目とその件数を確認します。
# 大陸ごとのデータ数
print("\n--- 大陸ごとのデータ数 ---")
print(df['continent'].value_counts())
# 国ごとのデータ数(多くの国があるので上位少しだけ表示)
print("\n--- 国ごとのデータ数 (上位5件) ---")
print(df['country'].value_counts().head())
- アジアとアフリカのデータが多いこと、各国は基本的に12年分のデータ(1952年から2007年まで5年ごと)を持っていることが推測できます。
3. 作図によるデータの理解
データの概要を掴んだところで、次はいよいよグラフを作成して、データのパターンや関係性を視覚的に探っていきましょう。ここでは、seaborn
ライブラリを中心に使いますが、matplotlib
での基本的な描き方も補足します。
3.1 散布図 (Scatterplot)
目的: 2つの数値変数の関係性を視覚化します。点がどのように分布しているかを見ることで、正の相関(一方が増えるともう一方も増える)、負の相関(一方が増えるともう一方が減る)、無相関などの傾向や、外れ値の存在などを確認できます。
例: 一人あたりGDP (gdpPercap
) と平均寿命 (lifeExp
) の関係を見てみましょう。経済的に豊かな国ほど平均寿命が高い傾向があるかを確認します。ここでは、2007年のデータに絞ってみます。
# 2007年のデータのみ抽出
df_2007 = df[df['year'] == 2007]
# Seaborn を使った散布図
plt.figure(figsize=(10, 6)) # グラフサイズを指定
sns.scatterplot(data=df_2007, x='gdpPercap', y='lifeExp', hue='continent', size='pop', sizes=(20, 2000), alpha=0.7)
plt.title('一人あたりGDPと平均寿命の関係 (2007年)')
plt.xlabel('一人あたりGDP ($)')
plt.ylabel('平均寿命 (歳)')
plt.xscale('log') # X軸を対数スケールにすると見やすくなることが多い
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') # 凡例をグラフの外に表示
plt.grid(True)
plt.show()
解釈のポイント:
- 全体的に、一人あたりGDPが高い国ほど平均寿命も高いという正の相関が見られます。
- X軸を対数スケールにすることで、GDPが低い国の分布が見やすくなっています。
hue='continent'
で大陸ごとに色分け、size='pop'
で人口の大きさを点のサイズで表現しています。これにより、どの地域のどの規模の国がどの位置にあるかが分かります。- アジア(青)やヨーロッパ(緑)はGDP、平均寿命ともに高い国が多い一方、アフリカ(赤)は低い国が多い傾向が見えます。
3.2 折れ線グラフ (Line graph)
目的: 時間の経過など、順序のある変数に対する数値変数の変化を追跡します。時系列データのトレンドや周期性を把握するのに適しています。
例: 日本 (Japan
) の平均寿命 (lifeExp
) がどのように推移してきたかを見てみましょう。
# 日本のデータのみ抽出
df_japan = df[df['country'] == 'Japan']
# Seaborn を使った折れ線グラフ
plt.figure(figsize=(10, 6))
sns.lineplot(data=df_japan, x='year', y='lifeExp', marker='o') # marker='o' でデータ点を表示
plt.title('日本の平均寿命の推移')
plt.xlabel('年')
plt.ylabel('平均寿命 (歳)')
plt.grid(True)
plt.show()
解釈のポイント:
- 年々、日本の平均寿命が一貫して上昇していることが明確にわかります。
- 線の傾きから、伸びが大きい時期とそうでない時期があることも読み取れます。
3.3 ヒストグラム (Histogram)
目的: 1つの数値変数の分布(どのような値がどのくらいの頻度で出現するか)を視覚化します。データがどの範囲に集中しているか、山がいくつあるか(単峰性、多峰性)、分布が左右対称か歪んでいるかなどを把握します。
例: 2007年における世界の国々の平均寿命 (lifeExp
) の分布を見てみましょう。
# 2007年のデータを使用 (df_2007)
# Seaborn を使ったヒストグラム
plt.figure(figsize=(10, 6))
sns.histplot(data=df_2007, x='lifeExp', kde=True, bins=15) # kde=True でカーネル密度推定も表示, binsで棒の数を調整
plt.title('世界の平均寿命の分布 (2007年)')
plt.xlabel('平均寿命 (歳)')
plt.ylabel('国の数(頻度)')
plt.grid(True)
plt.show()
解釈のポイント:
- 2007年時点では、平均寿命が70歳代後半の国が最も多いことがわかります。
- 分布を見ると、40歳代の国も一定数存在し、低い方に裾を引く(左に歪んだ)分布にも見えますが、比較的高い寿命の国が多い山と、低い寿命の国の小さな山の、二つの山(二峰性)があるようにも見えます。これは、先進国と発展途上国の間の差を反映している可能性があります。
kde=True
を指定すると、分布の滑らかな曲線(カーネル密度推定)も同時に描画され、全体の形状を捉えやすくなります。bins
の数を変えると棒の幅が変わり、見え方が変わることがあります。適切な数を設定することが重要です。
3.4 箱ひげ図 (Boxplot)
目的: カテゴリ変数の各水準(グループ)ごとに、数値変数の分布を比較します。中央値、四分位数(データのばらつき具合)、外れ値を簡潔に表現でき、グループ間の違いを把握するのに役立ちます。
例: 大陸 (continent
) ごとに平均寿命 (lifeExp
) の分布がどのように異なるかを見てみましょう (2007年データを使用)。
# 2007年のデータを使用 (df_2007)
# Seaborn を使った箱ひげ図
plt.figure(figsize=(12, 7))
sns.boxplot(data=df_2007, x='continent', y='lifeExp')
plt.title('大陸別の平均寿命の分布 (2007年)')
plt.xlabel('大陸')
plt.ylabel('平均寿命 (歳)')
plt.grid(True)
plt.show()
解釈のポイント:
- 箱:
- 箱の中の線は中央値(Median, データを小さい順に並べたときに真ん中に来る値、50パーセンタイル)を示します。
- 箱の下端は第1四分位数(Q1, 25パーセンタイル)、上端は第3四分位数(Q3, 75パーセンタイル)を示します。箱の長さ(高さ)は四分位範囲 (IQR = Q3 - Q1) と呼ばれ、データの中央50%がどの範囲に分布しているかを示します。
- ひげ: 箱から上下に伸びる線で、通常は Q1 - 1.5 * IQR から Q3 + 1.5 * IQR の範囲内にあるデータのうちの最小値・最大値までを示します。データのばらつきの範囲を表します。
- 点(外れ値): ひげの範囲から外れたデータは、点として個別にプロットされます。
- 比較:
- ヨーロッパとオセアニアは平均寿命の中央値が高く、箱も全体的に高い位置にあります。
- アフリカは中央値が最も低く、箱も低い位置にあり、ばらつき(箱の長さ)も比較的大きいことがわかります。他の大陸に比べて、寿命が短い国が多いことを示唆しています。
- アジアやアメリカ大陸は、アフリカとヨーロッパ/オセアニアの中間的な分布を示しています。
3.5 棒グラフ (Barplot)
目的: カテゴリ変数の各項目(カテゴリ)の頻度(数)や、カテゴリごとの数値変数の集計値(平均値、合計値など)を比較します。
例1: 各大陸に含まれる国の数(頻度)
# Seaborn を使った棒グラフ (頻度)
plt.figure(figsize=(10, 6))
sns.countplot(data=df_2007, x='continent', order=df_2007['continent'].value_counts().index) # orderで件数順に並び替え
plt.title('大陸ごとの国の数 (2007年)')
plt.xlabel('大陸')
plt.ylabel('国の数')
plt.grid(axis='y') # 横軸のグリッドのみ表示
plt.show()
解釈のポイント:
- 各大陸にデータが存在する国の数が比較できます。アフリカが最も多く、次いでアジア、ヨーロッパの順であることがわかります。(
value_counts()
の結果をそのままグラフにしたものと同じです。)
例2: 各大陸の平均寿命の平均値
seaborn.barplot
はデフォルトで平均値を計算してくれます。
# Seaborn を使った棒グラフ (平均値)
plt.figure(figsize=(10, 6))
# estimator=np.mean はデフォルトなので省略可, ci='sd'で標準偏差を示すエラーバーを表示
sns.barplot(data=df_2007, x='continent', y='lifeExp', ci='sd')
plt.title('大陸別の平均寿命 (2007年)')
plt.xlabel('大陸')
plt.ylabel('平均寿命の平均値 (歳)')
plt.grid(axis='y')
plt.show()
解釈のポイント:
- 各大陸に属する国々の平均寿命の「平均値」を比較しています。
- 棒の高さが平均値を示し、エラーバー(
ci='sd'
で指定)は標準偏差(データのばらつき具合)を表しています。 - オセアニアとヨーロッパの平均寿命が特に高く、アフリカが著しく低いことが明確にわかります。箱ひげ図で見た傾向と一致します。
4. まとめ
本講義では、データ分析の初期段階におけるデータ理解の重要性と、そのための具体的な手法として、記述統計量の確認および5種類の基本的なグラフ(散布図、折れ線グラフ、ヒストグラム、箱ひげ図、棒グラフ)の作成と解釈について学びました。
- 散布図: 2つの数値変数の関係(相関など)を見る。
- 折れ線グラフ: 時系列など順序のあるデータに対する変化を見る。
- ヒストグラム: 1つの数値変数の分布(頻度、形状)を見る。
- 箱ひげ図: カテゴリごとに数値変数の分布(中央値、ばらつき、外れ値)を比較する。
- 棒グラフ: カテゴリごとの頻度や集計値(平均など)を比較する。
これらの可視化手法を使いこなすことで、データに対する直感的な理解が深まり、その後のより高度な分析やモデリングの方針を立てる上で非常に役立ちます。
今後の学習:
- 今回学んだグラフのカスタマイズ(色、ラベル、サイズ、複数のグラフの組み合わせなど)
seaborn
が提供する他の高度なグラフ(ペアプロット、ヒートマップ、バイオリンプロットなど)- 統計的な仮説検定と組み合わせたデータの解釈
- インタラクティブな可視化ライブラリ(
plotly
,bokeh
など)の利用
データ分析において可視化は強力なツールです。ぜひ積極的に活用して、データからより多くの洞察を引き出せるように練習を続けてください。
5. 演習問題
前提:
以下のコードが実行され、gapminder
データが DataFrame
として変数 df
に読み込まれているものとします。
import pandas as pd
from gapminder import gapminder
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib # 日本語表示用(インストール済みとする)
# Seaborn のスタイル設定
sns.set_style('darkgrid')
# データの読み込み
df = gapminder
問題1:[ヒストグラム] 2007年の一人あたりGDPの分布
2007年における世界各国の「一人あたりGDP (gdpPercap
)」は、どのような分布になっているでしょうか? ヒストグラムを作成して確認してください。横軸(一人あたりGDP)は対数スケール (plt.xscale('log')
や sns.histplot
の log_scale=True
)にすると、分布の特徴がより明確になるかもしれません。
目的: 特定の年の経済指標(一人あたりGDP)が、どの範囲に集中しているか、どのような形状の分布をしているかを視覚的に把握する。
問題2:[折れ線グラフ] アフリカ大陸の平均寿命の推移
アフリカ大陸 (continent == 'Africa'
) に属する国々の平均寿命 (lifeExp
) は、1952年から2007年にかけてどのように変化してきたでしょうか? 各年におけるアフリカ大陸全体の平均寿命の平均値を計算し、その推移を折れ線グラフで示してください。
目的: 特定の地域(アフリカ大陸)における健康指標(平均寿命)の長期的なトレンドを視覚化する。
問題3:[散布図] 人口と一人あたりGDPの関係の変化(1952年 vs 2007年)
国の経済力(一人あたりGDP)と人口規模 (pop
) の間には、どのような関係があるでしょうか? また、その関係は時代によって変化したでしょうか? 1952年と2007年のそれぞれについて、横軸に一人あたりGDP (gdpPercap
)、縦軸に人口 (pop
) をとった散布図を作成し、比較してください。両方の軸を対数スケールにすると見やすくなります。
(ヒント:2つのグラフを別々に描画するか、hue
オプションを使って1つのグラフに年ごとの違いを色で表現する方法があります。)
目的: 2つの数値変数(人口、一人あたりGDP)の関係性を、異なる2つの時点で比較し、その変化を捉える。
問題4:[箱ひげ図] アメリカ大陸とアジア大陸のGDP分布比較 (2007年)
2007年において、アメリカ大陸 (Americas
) とアジア大陸 (Asia
) の国々では、一人あたりGDP (gdpPercap
) の分布にどのような違いがあるでしょうか? これら2つの大陸のデータを抽出し、大陸ごとに一人あたりGDPの分布を比較できる箱ひげ図を作成してください。縦軸(一人あたりGDP)は対数スケール (plt.yscale('log')
や sns.boxplot
の log_scale=True
) にすると比較しやすくなるでしょう。
目的: 特定のカテゴリグループ(アメリカ大陸 vs アジア大陸)間で、数値変数(一人あたりGDP)の分布の中心(中央値)、ばらつき(四分位範囲)、外れ値を比較する。
問題5:[棒グラフ] 各大陸の総人口 (2007年)
2007年時点での、各大陸の人口 (pop
) の合計値はどのようになっているでしょうか? 大陸ごとに人口の合計値を計算し、その結果を棒グラフで比較してください。どのグラフが最も多くの人口を抱えているか、視覚的に分かりやすく示しましょう。
目的: カテゴリ(大陸)ごとに数値変数(人口)の合計値を算出し、その大きさを棒グラフで比較する。