
記事のゴール
- 対象:Python 3.10+/pandas 2.x を使う初学者〜中級者
- ゴール:現場で毎週まわせる前処理パターン(=型)を、そのまま流用できる形で身につける
- 使い方:セクションごとに「狙い → 使いどころ → コピペ可コード → 実務メモ」の順で整理
基礎文法の次は、実務で毎回出る処理を“型”として覚える段階です。
本記事は、pandas 2.x を前提に、欠損・外れ値・結合・ウィンドウ関数・時系列・カテゴリ処理・集計の自動化・大規模データの分割処理・テスト/再現性まで、現場で即使えるレシピを体系化しました。
月末ミニプロジェクトのレビュー観点チェックリスト付き。週10時間×2〜3週で“回せる前処理”を手に入れます。
-
-
【保存版】pandas基礎:データフレームの作成・整形・結合・集計を“実務の型”で身につける
対象:未経験〜初学者/pandas 2.x・Python 3.10+ を想定ゴール:読み込み→選択→整形→結合→集計→欠損→日時→ピボット→出力まで、実務でそのまま使える書き方を10ステップで習得 デ ...
現場でつまずく3大ポイント
- 結合の地雷:キーの重複や型不一致に気づかず、行が爆増/欠落する。
- 時系列/ウィンドウ:
rolling/expanding/shiftの使い分けが曖昧で誤学習に繋がる。 - 品質保証:Notebookが一度は動いても、翌週に再現できない(データ差分/前処理の暗黙仕様)。
解決策は、事前チェック→明示的な型/キー管理→関数化→簡易テストのルーチン化。
本記事の“型”を丸ごと持ち帰ってください。
実体験メモ
「月次レポートの数値が前週とズレた」——原因はmerge前のキー重複。以降、validate="many_to_one"を絶対ルールにしてから事故はゼロになりました。
pandas実務レシピ 12パターン(Python 3.10+ / pandas 2.x)
以下は import pandas as pd 済みを前提。
サンプルデータ
orders.csv:order_id, order_date, customer_id, sku, qty, unit_price, store
customers.csv:customer_id, gender, age, area, signup_date
calendar.csv:date, dow, holiday_flag
1) 事前チェック(型・重複・分布)
狙い:読み込み時に型と欠損の取り扱いを最初に固定すると、後工程が安定します。
主キーは assert で即落ちるように。
コード(コピペ可)
import pandas as pd
def read\_orders(path: str) -> pd.DataFrame:
return pd.read\_csv(
path,
parse\_dates=\["order\_date"],
dtype={"customer\_id": "Int64", "sku": "string", "store": "category"},
na\_values=\["", "NA", "null"]
)
df = read\_orders("orders.csv")
# 基本プロファイル(軽量版)
print(df.info())
print(df.describe(numeric\_only=True))
print(df.isna().mean().sort\_values(ascending=False).head(10)) # 欠損率
# キー重複の検査(order\_idがユニークか)
assert not df\["order\_id"].duplicated().any(), "order\_id に重複があります"
使いどころ:以後の結合や集計が壊れる前に入口で止める。ログに理由(なぜこの型?)を残すとレビューが速い。
2) 欠損処理の型(意味を保つ)
狙い:数値は分布を崩しにくい代表値で、カテゴリは“未知”を明示化。
from statistics import median
num\_cols = \["qty", "unit\_price"]
# 数値:中央値で補完(分布の歪みが小さめ)
df\[num\_cols] = df\[num\_cols].apply(lambda s: s.fillna(median(s.dropna())))
# カテゴリ:"Unknown" で明示(分析時にフィルタ可能)
df\["store"] = df\["store"].cat.add\_categories(\["Unknown"]).fillna("Unknown")
判断基準:補完の根拠をコメントで残す(レビューでの誤解を防止)。
3) 外れ値の検知+Winsorize(軽量)
狙い:指標のロバスト性とビジネス影響のバランスをとる。
import numpy as np
amount = df\["qty"] \* df\["unit\_price"]
q\_low, q\_hi = amount.quantile(\[0.01, 0.99])
df\["amount\_clip"] = amount.clip(lower=q\_low, upper=q\_hi)
# 参考:z-scoreで粗い検知
z = (amount - amount.mean()) / amount.std(ddof=0)
df\["is\_outlier"] = (z.abs() > 3)
実務メモ:クリップした事実は必ずレポートに注記。
4) 結合前のキー健全性チェック
狙い:結合は安全設定がデフォルト。型を合せ、参照側は一意性を保証。
cust = pd.read_csv(
"customers.csv",
dtype={"customer_id": "Int64", "gender": "category", "area": "category"},
parse_dates=["signup_date"]
)
# 参照キーの重複チェック(customer\_idは一意か)
dups = cust\["customer\_id"].duplicated(keep=False)
assert not dups.any(), "customers: customer\_id が重複しています"
# 型合わせ(orders側と一致)
assert df\["customer\_id"].dtype == cust\["customer\_id"].dtype
# 安全な左結合(受注に顧客属性を付与)
joined = df.merge(cust, on="customer\_id", how="left", validate="many\_to\_one")
実務メモ:validate="many_to_one"で事故防止。一致しない型は明示変換してから結合。
5) カレンダーテーブルの活用(完全な時系列)
狙い:観測がない日も行を確保して、rolling や可視化でギザギザを回避。
cal = pd.read_csv("calendar.csv", parse_dates=["date"], dtype={"dow": "int8", "holiday_flag": "int8"})
# 受注を日次集約
daily = (
df.assign(date=df\["order\_date"].dt.date)
.groupby("date", as\_index=False)
.agg(sales=(lambda d: (d\["qty"]\*d\["unit\_price"]).sum()),
orders=("order\_id", "nunique"))
)
# カレンダーに結合して“穴のない”日次へ
full = cal.merge(daily, on="date", how="left").fillna({"sales": 0, "orders": 0})
実務メモ:以降の rolling/resample が安定。祝日フラグや曜日を特徴量にしやすい。
6) ウィンドウ関数(rolling/expanding/shift)
狙い:未来情報の混入(リーク)を防ぎつつ、短期トレンドと前年比を一括算出。
full = full.sort_values("date").reset_index(drop=True)
# 7日移動平均と前年比(365日シフト例)
full\["ma7"] = full\["sales"].rolling(window=7, min\_periods=1).mean()
full\["sales\_prev\_year"] = full\["sales"].shift(365)
full\["yoy"] = (full\["sales"] - full\["sales\_prev\_year"]) / full\["sales\_prev\_year"]
使いどころ:短期変動の平滑化+前年比比較。時系列の並び順を必ず保証。
7) カテゴリ処理(Top-N 固定と頻度エンコード)
狙い:カテゴリの散らばりを制御しつつ、学習前処理への橋渡しに。
# カテゴリの頻度で並べ替え(Top-Nを固定、その他は"Other")
TOP_N = 20
freq = df["sku"].value_counts()
major = freq.index[:TOP_N]
df["sku_top"] = df["sku"].where(df["sku"].isin(major), other="Other")
# 頻度エンコード(単純版)
sku\_freq = df\["sku"].value\_counts(normalize=True)
df\["sku\_freq"] = df\["sku"].map(sku\_freq)
実務メモ:説明可能性と汎化のバランス。モデル学習ではターゲットリークに注意。
8) グループ集計の自動化(“定義をデータ化”)
狙い:集計仕様が変わっても辞書を書き換えるだけで対応。
AGG_DEF = {
"amount": ["sum", "mean", "median"],
"qty": ["sum", "mean"],
}
df\["amount"] = df\["qty"] \* df\["unit\_price"]
agg = (
df.groupby(\[df\["order\_date"].dt.to\_period("M").astype(str), "store"], as\_index=False)
.agg(\*\*{f"{col}\_{fn}": (col, fn) for col, fns in AGG\_DEF.items() for fn in fns})
)
実務メモ:カラム命名規約({col}_{fn})を最初に固定すると認識ズレが減る。
9) メソッドチェーン+pipeで“読みやすく速い”前処理
狙い:小さな純関数に分割し、Notebook でもテストしやすい形に。
from typing import Callable
DF = pd.DataFrame
def add\_amount(d: DF) -> DF:
return d.assign(amount=d\["qty"] \* d\["unit\_price"]) # type: ignore
def add\_month(d: DF) -> DF:
return d.assign(ym=d\["order\_date"].dt.to\_period("M").astype(str))
def filter\_valid(d: DF) -> DF:
return d.query("qty > 0 and unit\_price > 0")
monthly = (
df.pipe(filter\_valid)
.pipe(add\_amount)
.pipe(add\_month)
.groupby(\["ym", "store"], as\_index=False)
.agg(sales=("amount", "sum"), orders=("order\_id", "nunique"))
)
実務メモ:各関数は入出力が DataFrame のみに。状態を持たせないとテストが楽。
10) 大規模データ:分割読み込み(chunksize)と段階保存
狙い:メモリに乗らない CSV を分割で処理し、重い工程の直後で中間保存。
chunks = pd.read_csv("orders.csv", chunksize=200_000, parse_dates=["order_date"])
acc = \[]
for ch in chunks:
ch = ch.query("qty > 0 and unit\_price > 0").assign(amount=ch\["qty"] \* ch\["unit\_price"]) # type: ignore
acc.append(
ch.groupby(ch\["order\_date"].dt.to\_period("M").astype(str), as\_index=False)
.agg(sales=("amount", "sum"))
)
monthly\_big = pd.concat(acc, ignore\_index=True).groupby("order\_date", as\_index=False).sum()
monthly\_big.to\_parquet("monthly\_sales.parquet", index=False) # 段階保存
実務メモ:集約は早めに。Parquet で再実行時間を短縮。I/O はボトルネックになりがち。
11) 品質保証:データ検査とpytestの最小セット
狙い:壊れたら即落ちるチェックを先頭に置き、再現性を担保。
data_checks.py
# data_checks.py
import pandas as pd
def check\_orders(df: pd.DataFrame) -> None:
assert (df\["qty"] >= 0).all(), "qty に負値があります"
assert (df\["unit\_price"] >= 0).all(), "unit\_price に負値があります"
assert df\["order\_id"].is\_unique, "order\_id が一意ではありません"
test_data_checks.py(pytest)
# test_data_checks.py
import pandas as pd
from data_checks import check_orders
def test\_check\_orders\_ok():
d = pd.DataFrame({"order\_id": \[1,2], "qty": \[1,2], "unit\_price": \[100,200]})
check\_orders(d) # 例外が出なければOK
実務メモ:Notebook でも最初に check_orders を呼ぶ習慣を。
12) 速度/メモリ最適化の最短メモ
- dtype 最適化:整数は
Int32/Int16、浮動はFloat32(精度要件と相談) - category 活用:
store/area/genderなどラベル列は category 化 - 列演算優先:
apply(axis=1)を避け、map/where/clipを使う - 不要列を早めに落とす:
drop(columns=...)、読み込みはusecolsで制限 - I/O 方針:中間は Parquet、配布は Excel/CSV
- 他ツール:更に大規模なら SQLite×Python や Polars も検討
迷ったら伴走を付ける
独学でも回せますが、レビュー(設計/仮説/評価まで)と質問対応があるとスピードと品質が段違い。
6ヶ月ロードマップに沿ってポートフォリオへ落とし込むなら、次の2校の無料相談から始めましょう。
- 株式会社キカガク:業務再現型の課題設計と出口支援。転職直結を狙う人に。
- Tech Academy:質問の速さ×短時間運用で継続しやすい。副業/在宅と相性◎。
TechAcademy データサイエンスコース(受講料:174,600円~ ※更に割引あり)

株式会社キカガク AI人材長期育成コース(受講料:237,600円~)

目的別の重点配分
- 転職(未経験→DS):
結合の健全性→カレンダー結合→ウィンドウ→品質保証を厚め。READMEと再現手順まで。 - 副業(自動化/レポート):
集計の自動化→ExcelWriter/Parquet→段階保存を厚め。納品テンプレへ。 - 在宅(短時間×高頻度):
pipeと小関数化で中断→再開が容易な構成に。
行動:月末ミニプロジェクト(レビュー観点付き)
課題:「月次×店舗の売上トレンドと前年比を作り、課題と打ち手を3行で示す」
orders.csvを読み、amount=qty*unit_priceとymを作成。calendar.csvと結合し、穴のない日次→月次に集約。rolling(7)で短期トレンド、shift(12)で前年同月比を計算。report.xlsxにmonthly/YoYを出力し、上位店舗のグラフを作成。- READMEに示唆(例:特定エリアのYoY低下→在庫/販促の仮説)を記載。
レビュー観点チェックリスト(コピペ可)
- [ ] 参照キーは一意か(
validate=使用) - [ ]
dtypeは明示か(カテゴリ/整数の最適化) - [ ] 欠損/外れ値の方針がコメントされているか
- [ ] メソッドチェーン/
pipeで読みやすいか - [ ] 中間成果(Parquet/Excel)の再現手順が残っているか
付録A:実務ユーティリティ関数(小さく速く)
from pathlib import Path
import pandas as pd
def to\_month(d: pd.Series) -> pd.Series:
return d.dt.to\_period("M").astype(str)
def read\_csv\_fast(path: str, usecols: list\[str] | None = None) -> pd.DataFrame:
return pd.read\_csv(path, usecols=usecols, low\_memory=False)
def ensure\_unique(df: pd.DataFrame, key: str) -> None:
assert df\[key].is\_unique, f"{key} is not unique"
def top\_n(df: pd.DataFrame, key: str, n: int = 20) -> pd.DataFrame:
return df.nlargest(n, key)
付録B:Notebook → スクリプト化の最短手順
- Notebookで
pipe小関数化→src/に切り出し if __name__ == "__main__":ブロックでI/Oを分離pytestでデータ検査だけ先に書くMakefileやタスクランナーで一発実行に
FAQ:よくある質問
Q1. rolling と expanding の違いは?
A. rolling は固定窓、expanding は累積。移動平均は rolling、累積比率は expanding。
Q2. 結合で行が増える/減るのですが?
A. まず value_counts で重複を特定。結合は validate="many_to_one" で即検知。
Q3. 中間ファイルはどこまで保存すべき?
A. 重い工程の直後と、レビュー共有が必要な集約結果。形式は Parquet が基本。
Q4. Excel 中心の現場への対策は?
A. ExcelWriter で複数シート、UTF-8 BOM 付き CSV、ピボット素材を渡すのが最短。
Q5. さらに速くしたい
A. 列演算の徹底・category 化に加え、必要なら SQLite×Python や Polars を検討。
この記事から次に読むべきもの(内部リンク)
-
-
【保存版】scikit-learn基礎:回帰・分類・前処理・パイプライン・交差検証を“実務の型”で習得
機械学習で迷子になる最大の理由は、前処理→学習→評価→改善の順番が曖昧なまま個々のアルゴリズムに飛びつくこと。 本記事は、未経験〜初学者が週10時間×2〜3週で到達できるscikit-learnの最短 ...
-
-
【保存版】モデル評価:指標の選び方・交差検証・閾値最適化・ビジネス接続を“実務の型”で解説
精度が上がらない原因の多くは「評価設計の誤り」にあります。 評価は「何点取れたか」を競うものではなく、意思決定に耐えうるか を検証する営みです。本記事は、回帰/分類/ランキングの 指標選定 → 交差検 ...
-
-
【保存版】可視化入門:Matplotlib/Plotlyの使い分けと“伝わるグラフ設計”10ステップ
結論:可視化は「きれいに描く」ことではなく、意思決定を動かすための設計です。 本稿では、未経験〜初学者が 週10時間×1〜2週 で、Matplotlib/Plotlyを軸に “伝わるグラフ”の設計と実 ...
-
-
はじめてのSQL:SELECT/WHERE/GROUP BYを最短で理解【コピペOK】
データ分析・自動レポート・簡易アプリの土台はSQLです。Pythonだけで押し切るより、前処理の7割をDB側で完結させる方が速く・安定します。本記事は、未経験〜初 学者が週10時間×2〜3週で、SEL ...
-
-
【保存版】SQLite×Pythonで作る“ローカルDWH”|ETL・集計・レポート自動化の最短手順
ローカルでゼロ構築、ファイル1つで完結、サーバ不要。 本記事はSQLite×Pythonで“毎日回る”ETL・集計・レポート自動化を最短で作るための完全ガイドです。データ設計→DB作成→ETL(取り込 ...
-
-
【保存版】データレポート納品の型:要件定義→ETL→検証→可視化→Excel/PDF→引き継ぎまで、失注しないワークフロー完全版
“いい分析”より“伝わる納品”。副業や実務で評価されるのは、意思決定に効く1枚と再現できるパッケージを期限通り出せること。 本記事は、未経験〜初学者が 週10時間×2〜3週 で、要件定義 → データ受 ...
最近のコメント