🐼 Pandas チートシート

# 🗓️ 基本操作

## 📦 インポート

```python
import pandas as pd
````

---

## 📁 データの読み込み・保存

```python
df = pd.read_csv("file.csv")     # CSV読み込み
df.to_csv("output.csv", index=False)  # CSV書き出し（indexなし）
```

---

## 👀 データの確認

```python
df.head()        # 最初の5行
df.tail()        # 最後の5行
df.info()        # データの概要
df.describe()    # 基本統計量
df.columns       # 列名一覧
df.shape         # 行数・列数（タプルで返す）
```

---

## 🧹 データの選択・絞り込み

```python
df["列名"]              # 単一列
df[["列1", "列2"]]      # 複数列
df.iloc[0]              # 行番号で取得（位置）
df.loc[0, "列名"]       # 行番号＆列名で取得（ラベル）

df[df["列名"] > 100]    # 条件で抽出
```

---

## 🧙‍♀️ データの加工・整形

```python
df["新列"] = df["A"] + df["B"]    # 新しい列作成
df.rename(columns={"旧名": "新名"}, inplace=True)  # 列名変更
df.drop("列名", axis=1, inplace=True)  # 列削除
df.fillna(0)           # 欠損を0で埋める
df.dropna()            # 欠損行の削除
df.duplicated()        # 重複行の判定
```

---

## 🧬 グループ集計・統計

```python
df.groupby("カテゴリ").mean()
df.groupby(["列1", "列2"]).sum()
df.groupby(["列1", "列2"]).size() # レコード件数を見たいとき
df["列"].value_counts()
df["列"].unique()
```

---

## 🔗 データの結合（merge, join, concat）

```python
# merge（SQL風JOIN）
pd.merge(df1, df2, how="inner", on="共通列")

# join（インデックスでくっつける）
df1.join(df2, how="left")

# concat（縦 or 横に結合）
pd.concat([df1, df2], axis=0)  # 行方向に結合
pd.concat([df1, df2], axis=1)  # 列方向に結合
```

---

## 🧱 インデックス操作

```python
df.set_index("列名", inplace=True)     # インデックスに設定
df.reset_index(inplace=True)          # インデックスを列に戻す
df.reset_index(drop=True, inplace=True)  # インデックス削除＆再振り直し
df.sort_index()                       # インデックスでソート
```

---

## 🧰 並べ替え・条件操作

```python
df.sort_values("列名", ascending=False)
df[df["列名"].isin(["A", "B"])]
df.query("列名 > 100 and 他の列 < 50")
```

---

## 🎁 おまけTips

```python
df.copy()          # データのコピー
df.sample(n=5)     # ランダムに抽出
df["列"] = df["列"].astype(str)        # 文字列型に変換
df["列"] = df["列"].astype(int)        # 整数型に変換（NaNがあるとエラー）
df["列"] = df["列"].astype(float)      # 浮動小数点型に変換
df["列"] = df["列"].astype(bool)       # ブール型に変換
```

# 🗓️ 日付操作

## 📦 日付の変換・作成

```python
pd.to_datetime("2023-05-01")                   # 文字列 → Timestamp
df["日付"] = pd.to_datetime(df["日付列"])      # 列全体を日付に変換
pd.date_range(start="2024-01-01", periods=7, freq="D")  # 日付の連続生成
````

---

## 📆 日付の分解（年・月・日・時間など）

```python
df["年"] = df["日付"].dt.year
df["月"] = df["日付"].dt.month
df["日"] = df["日付"].dt.day
df["曜日"] = df["日付"].dt.day_name()        # 曜日名
df["週番号"] = df["日付"].dt.isocalendar().week
df["時間"] = df["日付"].dt.hour
```

---

## ⏳ 日付差分の計算

```python
df["差分"] = df["日付"].diff()                   # 前の行との差分（Timedelta型）
df["経過日数"] = (df["日付"] - df["日付"].min()).dt.days
df["経過秒"] = df["差分"].dt.total_seconds()
```

---

## 🔍 日付によるフィルタリング

```python
df[df["日付"] >= "2024-01-01"]           # 2024年以降のデータ
df[df["日付"].dt.month == 5]             # 5月のデータ
```

---

## 📏 日付の丸め処理

```python
df["切り捨て"] = df["日付"].dt.floor("D")      # 日単位で切り捨て
df["切り上げ"] = df["日付"].dt.ceil("H")       # 時単位で切り上げ
df["丸め"] = df["日付"].dt.round("15T")        # 15分単位で四捨五入
```

---

## 📊 リサンプリング（時系列の再構成）

```python
df.set_index("日付", inplace=True)
df.resample("M").sum()     # 月ごとの合計
```

| freqコード   | 意味   |
| --------- | ---- |
| "D"       | 日    |
| "W"       | 週    |
| "M"       | 月末   |
| "MS"      | 月初   |
| "Q"       | 四半期末 |
| "A"       | 年末   |
| "H"       | 時間   |
| "T"/"min" | 分    |

---

## 🕒 時間の比較（datetime.time型）

```python
from datetime import time
df[df["日付"].dt.time > time(8, 0)]     # 8:00以降
```
---
## 🌐 タイムゾーンのついていないデータに tz を追加（ローカライズ）

```python
df["日付"] = pd.to_datetime(df["日付列"])
df["日付_JST"] = df["日付"].dt.tz_localize("Asia/Tokyo")    # JSTとして扱う（tzなし→あり）
```

---

## ⏱️ タイムゾーン付き日時の扱い

```python
df["日付"].dt.tz                # 現在のタイムゾーンの確認
df["日付"].dt.tz_convert("UTC")  # 別のtzへ変換
```

## 🌎 よく使うタイムゾーン

| タイムゾーン名           | 地域        |
| ----------------- | --------- |
| `"UTC"`           | 協定世界時     |
| `"Asia/Tokyo"`    | 日本標準時     |
| `"US/Eastern"`    | アメリカ東部標準時 |
| `"Europe/London"` | イギリス      |
---

## 🧪 UTCとローカル時間の混在に注意！

* `tz_localize()`：**tzがついていないdatetimeに“付ける”**
* `tz_convert()`：**すでにtzがあるdatetimeを“変換する”**

```python
# 正しい流れ
pd.to_datetime(df["日付"]).dt.tz_localize("Asia/Tokyo").dt.tz_convert("UTC")
```
---

# 🚫 NaN処理

## 🔍 NaNの確認・判定

```python
df.isna()           # NaNならTrue（DataFrame全体）
df["列"].isna()     # 列単位でのNaN判定
df.isnull()         # isna()と同じ
df.notna()          # NaNでないならTrue
````

---

## 🧹 NaNの除去

```python
df.dropna()                     # NaNを含む行をすべて削除
df.dropna(subset=["列名"])       # 特定の列にNaNがある行だけ削除
df.dropna(axis=1)              # NaNを含む列を削除
```

---

## 🧯 NaNの埋め方（fillna）

```python
df.fillna(0)                   # NaNを0で埋める
df.fillna(method="ffill")     # 前の値で埋める（forward fill）
df.fillna(method="bfill")     # 次の値で埋める（backward fill）
df["列"].fillna(df["列"].mean())  # 平均値で埋める（他に中央値・最頻値も可）
```

---

## 🤖 NaNの補間（interpolate）

```python
df["列"].interpolate()          # 線形補間（欠損を前後の数値から推定）
df["列"].interpolate(method="time")  # 時系列で補間（インデックスがdatetimeのとき）
```

---

## 💡 NaNがあるかどうかのチェック

```python
df.isna().sum()         # 各列のNaN件数を表示
df["列"].isna().any()   # TrueならNaNが存在する
df["列"].isna().sum()   # NaNの数を数える
```

---

## 📊 NaNが多い列の可視化（おまけ）

```python
df.isna().sum().sort_values(ascending=False).plot.bar()
```