Pandasの使い方
Pandas は、表データを『見た目のまま』扱うための道具です。行と列を保ったまま、選ぶ、増やす、集計する、別の表とつなぐ、といった操作を順に積み重ねられます。
このノートでは、成績表とプロフィール表を題材にしながら、表を読みやすく保ったまま加工していく流れを追います。大事なのは関数名の量よりも、各時点で表の形がどう変わったかを意識することです。
まずは 1 枚の表を読む
Pandas に慣れていないうちは、コードを追う前に『この表は 1 行が何を表し、1 列が何を表しているか』をはっきりさせるのが重要です。そこが見えていれば、列選択も集計も結合も、全部『表のどこを触っているか』として理解できます。
このノートでは、1 枚の成績表から始めて、必要な列だけを抜き出し、新しい列を加え、クラブ別に集計し、欠損を埋め、別表と結合し、最後に縦持ちへ変形します。
つまり、単発の API 集ではなく、『分析の前処理で表が少しずつ整理されていく過程』をそのままたどる構成です。
表を操作するときの基本語彙
DataFrame は行と列を持つ表そのものです。1 列だけ抜き出すと Series になり、複数列を保つと DataFrame のまま残ります。
groupby は同じ値を持つ行をまとめて見る操作、merge は別の表をキーでつなぐ操作、NaN は値が欠けている場所を表す印です。どれも実務では頻出ですが、やっていること自体は『表を整理して読みやすくする』に尽きます。
表がどう変わったかを追いながら読む
Pandas では、処理そのものより『処理のあと表が何列になり、どの行が残り、どこに NaN が入ったか』を読むことが大切です。各セルでは、その変化を出力から確かめながら進めてください。
同じ表を、用途に合わせて整える
このあと出てくる agg, merge, melt はどれも少し記号が多く見えますが、目的は単純です。
agg: まとめ方を指定して集計表を作るmerge: 別の表から必要な列を持ってくるmelt: 横に広がった列を、縦に積み替えて扱いやすくする
『何のために形を変えているか』を先に押さえると、書式に振り回されにくくなります。
import numpy as np
import pandas as pd
まずは手で DataFrame を作って、1 行が 1 人、1 列が 1 項目になっていることを確かめます。Pandas を読むときの基本は、この表の見取り図を頭の中に置いたまま進むことです。
df = pd.DataFrame({
"student": ["A", "B", "C", "D", "E"],
"grade": [1, 1, 2, 2, 2],
"math": [72, 88, 91, 67, 79],
"english": [75, 90, 85, 70, 82],
"club": ["AI", "Art", "AI", "Sports", "AI"],
})
df
列選択と条件抽出は、表を読む最初の動作です。
df["math"] が 1 列だけの Series を返し、df[["student", "math"]] が 2 列の DataFrame を返すのは、後続の処理を変える重要な違いです。見た目はかっこ 1 つの差でも、表のまま残すのか、1 本の列として扱うのかが分かれています。
print(df[["student", "math"]])
print("---")
print(df[df["math"] >= 80])
新しい列を足すと、表は『読むだけのもの』から『自分で作り変えるもの』に変わります。ここでは合計点と判定ラベルを加えます。
np.where(...) は、各行ごとに条件を見て値を返す書き方です。1 行ずつ if 文で回す代わりに、表全体へまとめて条件をかけています。
df["total"] = df["math"] + df["english"]
df["pass"] = np.where(df["total"] >= 160, "pass", "retry")
df
groupby は、同じカテゴリの行をまとめて眺める操作です。クラブ別の平均点を見ると、『クラス全体では見えなかった傾向が、集団ごとには見える』ことが分かります。
students=("student", "count") は、出力列名を students にして、student 列へ count をかける、という指定です。ここは呪文に見えやすいですが、実際には『どの列を、どう集計し、何という名前で返すか』を並べているだけです。
club_summary = (
df.groupby("club", as_index=False)
.agg(
students=("student", "count"),
math_mean=("math", "mean"),
english_mean=("english", "mean"),
)
)
club_summary
欠損値は、現実のデータではほぼ必ず出ます。大事なのは、いきなり埋めることではなく、まず『どこが抜けているか』を確かめることです。欠損の位置を見ないまま処理を進めると、集計結果の解釈を誤りやすくなります。
loc は、行名と列名を指定して表の一部を取り出したり、書き換えたりするときに使います。今回の df_missing.loc[2, "english"] は、『行番号 2 の人の english 列』という 1 マスを指しています。
ここではその 1 マスに np.nan を入れて、わざと欠損値を作っています。つまり loc は、表の中の「どこを触るか」をはっきり指定するための書き方です。
df_missing = df.copy()
df_missing.loc[2, "english"] = np.nan
print(df_missing)
print("--- 欠損数 ---")
print(df_missing.isna().sum())
ここでは説明を単純にするため、列平均で穴埋めします。もちろん実務では、中央値の方がよい場合も、そもそも埋めない方がよい場合もあります。
大事なのは『NaN をどう扱うかを自分で決める』ことで、自動的にきれいな値になると思わないことです。
filled = df_missing.copy()
filled["english"] = filled["english"].fillna(filled["english"].mean())
filled
merge は、別々の表に分かれている情報を 1 つの表へ戻す操作です。
how="left" は、左側の成績表の行を必ず残しながら、対応するプロフィールがあれば右側から付け足す、という意味です。『誰を基準に残すのか』を意識して読むと、join の種類が整理しやすくなります。
profile = pd.DataFrame({
"student": ["A", "B", "C", "D", "E"],
"city": ["Tokyo", "Osaka", "Nagoya", "Fukuoka", "Tokyo"],
"hours": [6.5, 4.0, 7.0, 3.5, 5.0],
})
merged = pd.merge(df, profile, on="student", how="left")
merged
melt は、横に広がった科目列を縦へ積み替える操作です。最初は形が崩れたように見えますが、可視化や科目別集計ではこちらの方が扱いやすい場面が多いです。
1 行に 1 科目ずつ並ぶ形になるので、『student, subject, score』という tidy な表へ近づきます。
long_df = merged.melt(
id_vars=["student", "club"],
value_vars=["math", "english"],
var_name="subject",
value_name="score"
)
long_df.head(10)
日付を文字列のまま持っていると、月ごとの集計や並び替えが不安定になります。datetime に変えておくのは、時間を文字ではなく時刻として扱う準備です。
sales = pd.DataFrame({
"date": ["2026-01-02", "2026-01-14", "2026-02-03", "2026-02-10", "2026-03-01"],
"amount": [120, 95, 140, 110, 180]
})
sales["date"] = pd.to_datetime(sales["date"])
sales["month"] = sales["date"].dt.to_period("M")
monthly = sales.groupby("month", as_index=False)["amount"].sum()
monthly
Pandas の前処理で大切なのは、表の形を自分で説明できることです。どの列を残したのか、どのキーで結合したのか、どこに欠損があったのか。そこが曖昧だと、モデル以前にデータの意味を見失います。
逆に、その形の変化を追えるようになると、Pandas のコードはかなり読みやすくなります。
まとめ
このノートで一番大事なのは、Pandas を『表を整理するための道具』として見ることです。難しいメソッド名を全部覚えるよりも、今していることが 列を見る、行をしぼる、新しい列を足す、表の形を変える のどれなのかを意識すると、コードがかなり読みやすくなります。
特に最初は、df["列名"] で列を見る、df[df["列名"] > ...] で条件に合う行を取り出す、df.loc[...] や df.iloc[...] で場所を指定する、この 3 つを押さえるだけでも十分です。その上で、groupby は同じ仲間ごとにまとめる、merge は別の表をつなぐ、melt は横長の表を縦に並べ替える、と理解すると全体がつながって見えてきます。
また、NaN のような欠損値が出てきたときは、すぐ埋めるより先に『どこが欠けているのか』を見ることが大切です。Pandas の処理では、コードそのものよりも、処理の前後で表の形や中身がどう変わったかを確認する姿勢が重要です。
参照方法の整理
Pandas の参照方法は多く見えますが、実際には次の 4 つに分けて覚えると整理しやすいです。
- 列を見る
- 行を見る
- 1 つの値を見る
- 表全体の情報を見る
この分類で見ると、似た書き方の違いも分かりやすくなります。たとえば loc は「ラベル名で指定する」、iloc は「位置で指定する」という違いです。
1. 列を見る
列を取り出すときは、まずカラム名で選ぶ形を覚えるのが基本です。1 列なら Series、複数列なら DataFrame になります。
| 目的 | 書き方 | 説明 |
|---|---|---|
1つの列を Series で取得 |
df["名前"] |
カラム名で 1 列だけ取り出す基本形 |
複数列を DataFrame で取得 |
df[["名前", "出身"]] |
二重カッコで複数列を選ぶ |
| 列番号で 1 列目を取得 | df.iloc[:, 0] |
位置で指定して 1 列取り出す |
列番号で 1 列目を DataFrame として取得 |
df.iloc[:, [0]] |
1 列でも表の形を保ちたいときに使う |
| 全カラム名を見る | df.columns |
カラム名の一覧を確認する |
| カラム名をリスト化する | df.columns.tolist() |
カラム名を Python のリストにする |
| 新しいカラムを追加する | df["学年"] = [3, 2, 1] |
新しい列を右端に追加する |
| カラムを削除する | df.drop("年齢", axis=1) |
指定した列を削除する |
| カラムの順番を並べ替える | df = df[["出身", "名前", "年齢"]] |
好きな順に列を並べ替える |
2. 行を見る
行を取り出すときは、「位置で取るのか」「条件でしぼるのか」を分けて考えると理解しやすいです。
| 目的 | 書き方 | 説明 |
|---|---|---|
| 行番号で 1 行取得 | df.iloc[0] |
0 行目を位置で取り出す |
| 行番号で複数行取得 | df.iloc[[0, 2]] |
0 行目と 2 行目をまとめて取り出す |
| インデックス名で取得 | df.loc[0] |
ラベルを使って行を取り出す |
| 条件で複数行取得 | df[df["年齢"] > 18] |
条件に合う行だけ取り出す |
3. 1つの値を見る・変える
表の中の 1 マスを直接指定したいときに使うのが loc と iloc です。df.loc[0, "年齢"] = 21 のように書けば、どの行のどの列を書き換えるかをはっきり指定できます。
| 目的 | 書き方 | 説明 |
|---|---|---|
| 行番号と列番号で値を取る | df.iloc[0, 1] |
0 行 1 列の値を位置で取得する |
| 行ラベルと列名で値を取る | df.loc[0, "名前"] |
ラベルで 1 つの値を取得する |
| 特定の値を書き換える | df.loc[0, "年齢"] = 21 |
指定した 1 マスの値を更新する |
| 全データを配列で見る | df.values |
表全体を NumPy 配列として取り出す |
4. 表全体の状態を見る
細かく中身を見る前に、表の大きさや型をざっと確認すると、その後の作業がかなり進めやすくなります。
| 内容 | 書き方 | 説明 |
|---|---|---|
| 行数・列数 | df.shape |
表が何行何列かを見る |
| データ型 | df.dtypes |
各列が文字列か数値かなどを確認する |
最初の n 行 |
df.head(3) |
冒頭だけ見て表の雰囲気をつかむ |
最後の n 行 |
df.tail(2) |
末尾のデータを確認する |
| 概要情報 | df.info() |
欠損や型をまとめて見る |
| 統計情報 | df.describe() |
数値列の平均や分布をざっと見る |
5. インデックスを扱う
インデックスは、行についた名前のようなものです。普段は 0, 1, 2... の連番ですが、列をインデックスに変えるとデータの見方が変わります。
| 目的 | 書き方 | 説明 |
|---|---|---|
| インデックス一覧を見る | df.index |
行ラベルの一覧を確認する |
| インデックスをリスト化する | df.index.tolist() |
行ラベルをリストにする |
| インデックスを列に戻す | インデックスを通常の列に戻す | |
| 列をインデックスにする | df.set_index("名前") |
名前 列を行ラベルとして使う |
覚え方のコツ
最初は全部を暗記しようとせず、次の 4 つを使い分けられれば十分です。
df["列名"]: 列を見るdf[df["列名"] > 条件]: 条件で行をしぼるdf.loc[...]: ラベル名で場所を指定するdf.iloc[...]: 番号で場所を指定する
この 4 つを軸にして、必要になったら columns、shape、head() などを足していくと、Pandas の参照方法はかなり整理して理解できます。