K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

pandas の基本操作

01.2.2

pandas の基本操作

最終更新 2024-06-01 読了時間 4 分
まとめ
このページは、前のページで整形した総務省の歳出データ soumu-gdp-clean.csv(行がカテゴリ、列が年度)を使って、pandas DataFrame の基本操作を順に確かめるリファレンスです。info() と describe().T でメタ情報を見たあと、列名を「平成1年度」→「H1」のように短くし、loc[条件, 列] と iloc[行番号, 列番号] で行・列を取り出します。assign で差分列 diff と平均列 avg を足し、filter(regex="^(H|R)") で年度列をまとめて扱い、melt で「カテゴリ・year・value」の long 形式に、pivot_table でその逆に変換します。最後に to_parquet と to_csv の 2 形式で保存するまでを扱い、次ページの agg と SQL の例でそのまま使える df と tidy を作ります。

ここで使うデータは sample-data で整形した soumu-gdp-clean.csv です。

直感 #

Excel で表を扱うときの「列を選ぶ」「条件で行を絞る」「計算列を足す」「ピボットテーブルを作る」が、pandas では loc・assign・melt・pivot_table の 4 つに対応します。違いは、Excel の操作が手作業で残らないのに対し、pandas ではすべてがコードとして残るので、データが更新されても同じ処理を 1 回の実行で再現できる点です。このページでは 1 つの DataFrame に対してその 4 つを順に適用し、最後に 2 つの形式で保存するところまでをたどります。

次のコードは整形済み CSV を読み込み、先頭 5 行を表示します。

1
2
3
4
5
6
from pathlib import Path
import pandas as pd

DATA = Path("../data/processed/soumu-gdp-clean.csv")
df = pd.read_csv(DATA)
df.head()

1. メタ情報の確認 #

次のコードは、行数・列数・欠損数の一覧と、列ごとの平均・標準偏差・最小・最大を表示します。

1
2
df.info()
df.describe().T[['mean','std','min','max']].round(2).head()

列の正規化 #

次のコードは「平成1年度」を「H1」、「令和1年度」を「R1」のように短い列名に置き換えます。

1
2
3
4
5
6
df.columns = (
    df.columns
      .str.replace("年度", "")
      .str.replace("令和", "R")
      .str.replace("平", "H")
)

2. 行・列選択 (loc / iloc) #

次のコードは、「社会保障関係費」の行から 4 つの列を名前で取り出し、続けて先頭 3 行 × 5 列を位置で取り出します。

1
2
df.loc[df["カテゴリ"] == "社会保障関係費", ["カテゴリ", "H1", "H10", "R1"]]
df.iloc[:3, :5]  # 位置ベース

頻出パターンを関数化しておくと便利です。次のコードは「カテゴリ名と列のリストを渡すと該当行を返す」関数を定義し、「教育費」で試します。

1
2
3
4
def pick(category, cols):
    return df.loc[df["カテゴリ"] == category, cols]

pick("教育費", ["H1", "H5", "R1"])

3. 行フィルタと新列 #

次のコードは、令和 1 年度と平成 1 年度の差が 5 を超えるカテゴリに絞り、差分 diff と年度平均 avg の列を足して差分の大きい順に並べます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mask = (df["R1"] - df["H1"]) > 5
growth = (
    df.assign(
        diff = df["R1"] - df["H1"],
        avg  = df.filter(regex="^(H|R)").mean(axis=1)
    )
    .loc[mask, ["カテゴリ", "diff", "avg"]]
    .sort_values("diff", ascending=False)
)
growth.head()

4. 形の変換(long/ wide) #

次のコードは、「カテゴリ × 年度」の横長の表を、「カテゴリ・year・value」の 3 列に縦に並べ直し、年度の文字列を西暦の整数に変換します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
value_cols = df.columns[df.columns != "カテゴリ"]

tidy = (
    df.melt(
        id_vars="カテゴリ",
        value_vars=value_cols,
        var_name="year",
        value_name="value"
    )
    .assign(
        year = lambda x: x["year"].str.replace("H", "19").str.replace("R", "20").astype(int)
    )
)
tidy.head()

melt で long 形式をつくっておくと、groupby や可視化ライブラリに渡しやすくなります。

逆に列を広げたい場合は pivot_table を使用します。次のコードは tidy を「行が year、列がカテゴリ」の表に戻します。

1
2
3
4
5
pivot = tidy.pivot_table(
    index="year",
    columns="カテゴリ",
    values="value"
)

5. 書き出しとログ #

次のコードは、wide 形式の df を Parquet に、long 形式の tidy を CSV に保存します。

1
2
df.to_parquet("../data/processed/soumu-gdp-clean.parquet", index=False)
tidy.to_csv("../data/processed/soumu-gdp-tidy.csv", index=False, encoding="utf-8-sig")

よく使うメソッド早見表 #

操作pandas例
行・列抽出loc / ilocdf.loc[df["R1"]>30, ["カテゴリ","R1"]]
列の追加assigndf.assign(diff=df["R1"]-df["H1"])
列の一括変換filter + applydf.filter(regex="^H").apply(pd.to_numeric)
集計groupby / aggtidy.groupby("year").agg({"value":"sum"})
形の変換melt / pivot_tablelong ↔ wide

チェックリスト #

最初に確認したいのは、info() と describe() で異常値・欠損・型を把握したかです。二つ目は列名を H1 / R1 に正規化し、filter(regex=...) で年度列をまとめて扱えるようにしたかで、三つ目は assign / loc を使って mask 変数のある可読性の高いフィルタリングを書いたかです。四つ目は long 形式(melt)を作り、groupby や可視化に使い回せるようにしたか、最後に保存時に encoding="utf-8-sig" とフォーマット(CSV / Parquet)を明示したかを見ます。

ここで整理した DataFrame は、次ページの agg や SQL 例でそのまま使いまわします。