Pandasマスター講座：高度なデータ分析テクニック15選

## 1. Pandasの基本

Pandasは、Pythonでデータ分析を行うための強力なライブラリです。DataFrameとSeriesという2つの主要なデータ構造を提供し、大量のデータを効率的に処理できます。まずは、50件のサンプルデータを作成し、基本的な操作を見ていきましょう。

```python
import pandas as pd
import numpy as np

# 50件のサンプルデータを作成
np.random.seed(0)
data = {
    '名前': [f'社員{i}' for i in range(1, 51)],
    '年齢': np.random.randint(22, 60, 50),
    '部署': np.random.choice(['営業', '技術', '人事', '経理'], 50),
    '給与': np.random.randint(300000, 800000, 50),
    '勤続年数': np.random.randint(0, 30, 50)
}

df = pd.DataFrame(data)
print(df.head())
```

## 2. データの基本情報の取得

データフレームの基本情報を取得することは、データ分析の第一歩です。行数、列数、データ型、欠損値の有無などを確認しましょう。

```python
# データフレームの基本情報を表示
print(df.info())

# 統計情報を表示
print(df.describe())

# 欠損値の確認
print(df.isnull().sum())
```

## 3. データの選択と抽出

Pandasでは、様々な方法でデータを選択・抽出できます。インデックス、列名、条件式などを使って必要なデータにアクセスする方法を学びましょう。

```python
# 特定の列を選択
print(df['年齢'])

# 複数の列を選択
print(df[['名前', '部署', '給与']])

# 条件に基づいて行を選択
print(df[df['年齢'] > 40])

# locを使用して行と列を選択
print(df.loc[0:5, ['名前', '給与']])

# ilocを使用してインデックスで選択
print(df.iloc[0:5, 1:3])
```

## 4. データの集計と要約

データの集計は分析の重要な部分です。グループ化や集計関数を使って、データの要約統計量を計算する方法を見ていきます。

```python
# 部署ごとの平均給与を計算
print(df.groupby('部署')['給与'].mean())

# 部署ごとの年齢の最小値、最大値、平均値を計算
print(df.groupby('部署')['年齢'].agg(['min', 'max', 'mean']))

# 部署と年齢層でグループ化し、給与の平均を計算
df['年齢層'] = pd.cut(df['年齢'], bins=[0, 30, 40, 50, 100], labels=['20代', '30代', '40代', '50代以上'])
print(df.groupby(['部署', '年齢層'])['給与'].mean().unstack())
```

## 5. データの変換と整形

データ分析では、元のデータを変換したり整形したりする必要がしばしばあります。列の追加、データ型の変換、欠損値の処理などの方法を学びましょう。

```python
# 新しい列を追加（ボーナス = 給与の10%）
df['ボーナス'] = df['給与'] * 0.1

# データ型の変換（給与を文字列に）
df['給与_文字列'] = df['給与'].astype(str)

# 欠損値の挿入と処理
df.loc[0:5, '勤続年数'] = np.nan
df['勤続年数'] = df['勤続年数'].fillna(df['勤続年数'].mean())

print(df.head(10))
```

## 6. データのソートと並べ替え

データを特定の列に基づいてソートすることで、傾向や外れ値を見つけやすくなります。複数の列を使った高度なソートも可能です。

```python
# 給与で降順にソート
print(df.sort_values('給与', ascending=False).head())

# 部署でソートし、さらに給与で降順にソート
print(df.sort_values(['部署', '給与'], ascending=[True, False]).head(10))

# インデックスでソート
df_shuffled = df.sample(frac=1)  # データをシャッフル
print(df_shuffled.sort_index().head())
```

## 7. データのマージと結合

複数のデータフレームを組み合わせることで、より豊富な情報を得ることができます。様々な結合方法を使って、データを統合する方法を見ていきましょう。

```python
# 新しいデータフレームを作成（部署ごとの予算）
budget_data = {
    '部署': ['営業', '技術', '人事', '経理'],
    '予算': [10000000, 15000000, 5000000, 8000000]
}
df_budget = pd.DataFrame(budget_data)

# 内部結合
df_merged = pd.merge(df, df_budget, on='部署')

# 外部結合
df_outer = pd.merge(df, df_budget, on='部署', how='outer')

print(df_merged.head())
print(df_outer.head())
```

## 8. 時系列データの処理

Pandasは時系列データの処理に強みを持っています。日付や時刻のデータを扱う方法、リサンプリング、移動平均の計算などを学びましょう。

```python
# 日付インデックスを持つデータフレームを作成
dates = pd.date_range('2023-01-01', periods=50, freq='D')
ts_data = pd.DataFrame({'値': np.random.randn(50)}, index=dates)

# 月次データにリサンプリング
monthly_data = ts_data.resample('M').mean()

# 7日間の移動平均を計算
rolling_mean = ts_data.rolling(window=7).mean()

print(ts_data.head())
print(monthly_data)
print(rolling_mean.head(10))
```

## 9. ピボットテーブルとクロス集計

ピボットテーブルとクロス集計は、データを再構成して新しい洞察を得るのに役立ちます。複雑なデータの要約を簡単に作成できます。

```python
# ピボットテーブルの作成
pivot_table = pd.pivot_table(df, values='給与', index='部署', columns='年齢層', aggfunc='mean')

# クロス集計
cross_tab = pd.crosstab(df['部署'], df['年齢層'])

print(pivot_table)
print(cross_tab)
```

## 10. データの可視化

Pandasは、Matplotlibと連携して簡単にデータを可視化できます。基本的なグラフの作成方法を見ていきましょう。

```python
import matplotlib.pyplot as plt

# 棒グラフ：部署ごとの平均給与
df.groupby('部署')['給与'].mean().plot(kind='bar')
plt.title('部署別平均給与')
plt.show()

# 散布図：年齢と給与の関係
plt.figure(figsize=(10, 6))
plt.scatter(df['年齢'], df['給与'])
plt.xlabel('年齢')
plt.ylabel('給与')
plt.title('年齢と給与の関係')
plt.show()
```

## 11. 高度なデータ操作：apply と applymap

`apply`と`applymap`メソッドを使用すると、データフレームやシリーズに対してカスタム関数を適用できます。これにより、複雑なデータ変換や計算が可能になります。

```python
# 給与に基づいて等級を付ける関数
def salary_grade(salary):
    if salary < 400000:
        return 'C'
    elif salary < 600000:
        return 'B'
    else:
        return 'A'

# apply を使用して新しい列を作成
df['給与等級'] = df['給与'].apply(salary_grade)

# applymap を使用してデータフレーム全体に関数を適用
df_normalized = df[['年齢', '給与', '勤続年数']].applymap(lambda x: (x - x.mean()) / x.std())

print(df[['名前', '給与', '給与等級']].head(10))
print(df_normalized.head())
```

## 12. 欠損値の高度な処理

実際のデータセットでは、欠損値の処理が重要になります。単純な削除や平均値での補完以外にも、様々な方法があります。

```python
# 意図的に欠損値を作成
df.loc[0:10, '給与'] = np.nan
df.loc[20:25, '年齢'] = np.nan

# 前方補完
df['給与_前方補完'] = df['給与'].fillna(method='ffill')

# 線形補間
df['年齢_補間'] = df['年齢'].interpolate()

# 多重代入法（簡易版）
from sklearn.impute import SimpleImputer

imputer = SimpleImputer(strategy='mean')
df_imputed = pd.DataFrame(imputer.fit_transform(df[['年齢', '給与']]), columns=['年齢_imputed', '給与_imputed'])

print(df[['給与', '給与_前方補完']].head(15))
print(df[['年齢', '年齢_補間']].head(30))
print(df_imputed.head())
```

## 13. 高度なグループ操作

グループ化されたデータに対して、より複雑な操作を行う方法を見ていきます。カスタム集計関数の適用や、グループ内での相対的な計算などが可能です。

```python
# カスタム集計関数
def top_3_avg(x):
    return x.nlargest(3).mean()

# グループごとに複数の集計を実行
advanced_agg = df.groupby('部署').agg({
    '給与': ['mean', 'median', top_3_avg],
    '年齢': ['min', 'max', 'std']
})

# グループ内での相対的な計算
df['給与_部署内相対'] = df.groupby('部署')['給与'].transform(lambda x: (x - x.mean()) / x.std())

print(advanced_agg)
print(df[['名前', '部署', '給与', '給与_部署内相対']].head(10))
```

## 14. 時系列データの高度な分析

時系列データに対して、より高度な分析手法を適用します。季節性の分解、自己相関の計算、移動相関などを行います。

```python
import pandas as pd
import numpy as np
from statsmodels.tsa.seasonal import seasonal_decompose
import matplotlib.pyplot as plt

# より長い時系列データを生成
dates = pd.date_range('2020-01-01', periods=730, freq='D')
ts = pd.Series(np.random.randn(730).cumsum() + 20 + np.sin(np.arange(730) * 2 * np.pi / 365) * 10, index=dates)

# 季節性分解
result = seasonal_decompose(ts, model='additive', period=365)

# プロット
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, figsize=(12, 16))
result.observed.plot(ax=ax1)
ax1.set_title('Observed')
result.trend.plot(ax=ax2)
ax2.set_title('Trend')
result.seasonal.plot(ax=ax3)
ax3.set_title('Seasonal')
result.resid.plot(ax=ax4)
ax4.set_title('Residual')
plt.tight_layout()
plt.show()

# 自己相関
from pandas.plotting import autocorrelation_plot
autocorrelation_plot(ts)
plt.show()

# 移動相関
ts2 = ts.shift(30) + np.random.randn(730) * 5
rolling_corr = ts.rolling(window=90).corr(ts2)
rolling_corr.plot()
plt.title('90日移動相関')
plt.show()
```

## 15. 高度なインデックス操作とマルチインデックス

Pandasの高度な機能の一つとして、複雑なインデックス操作とマルチインデックスの使用があります。これらを活用することで、より柔軟なデータ分析が可能になります。

```python
# マルチインデックスの作成
multi_index = pd.MultiIndex.from_product([['営業', '技術', '人事', '経理'], ['正社員', '契約社員']], names=['部署', '雇用形態'])
df_multi = pd.DataFrame(np.random.randn(8, 3), index=multi_index, columns=['売上', '経費', '利益'])

# レベル別の集計
print(df_multi.groupby(level='部署').mean())
print(df_multi.groupby(level='雇用形態').mean())

# インデックスのリセットとセット
df_reset = df_multi.reset_index()
print(df_reset.head())

df_set = df_reset.set_index(['部署', '雇用形態'])
print(df_set.head())

# クロスセクション選択
print(df_multi.xs('正社員', level='雇用形態'))

# インデックス名の変更
df_multi.index.names = ['Division', 'EmploymentType']
print(df_multi.head())
```

## まとめ

この記事では、Pandasの高度な使い方について15の章にわたって詳しく解説しました。主な内容は以下の通りです：

1. Pandasの基本と50件のサンプルデータの作成
2. データの基本情報の取得方法
3. データの選択と抽出テクニック
4. データの集計と要約統計量の計算
5. データの変換と整形手法
6. データのソートと並べ替え
7. 複数のデータフレームのマージと結合
8. 時系列データの処理方法
9. ピボットテーブルとクロス集計の作成
10. Pandasを使用したデータの可視化
11. apply と applymap を使用した高度なデータ操作
12. 欠損値の高度な処理方法
13. グループ化されたデータに対する複雑な操作
14. 時系列データの高度な分析テクニック
15. 高度なインデックス操作とマルチインデックスの使用

これらの技術を習得することで、より効率的で洞察力のあるデータ分析が可能になります。Pandasは非常に強力なライブラリであり、これらの高度な機能を使いこなすことで、複雑なデータ処理タスクも簡単に実行できるようになります。

データ分析の実践では、ここで紹介した技術を組み合わせて使用することが多いでしょう。例えば、データの前処理として欠損値を処理し、必要な特徴量を抽出した後、グループ化して集計を行い、最後に結果を可視化するといった流れです。

Pandasの機能を十分に活用することで、データからより多くの価値を引き出し、より良い意思決定につなげることができます。継続的な学習と実践を通じて、Pandasのスキルを磨いていくことをお勧めします。