pandasとは、表形式のデータ(DataFrame)を読み込み・抽出・集計・結合するためのPythonのライブラリです。Excelでやっている「絞り込み」「並べ替え」「ピボット」を、数行のコードで何度でも同じように再現できます。

この記事は、「やりたいこと」から引ける逆引き81項目です。すべて同じ6行のサンプルデータで実際に実行し、出力をコードのすぐ下に # コメントで載せています(そのまま貼っても動きます)。検証は pandas 3.0.6 / Python 3.13.7 です。2026年1月に出た pandas 3.0 で変わった点(Copy-on-Writeが既定になった、文字列が str 型になった、append がない)も、実際のエラー文・警告文と置き換え表でまとめました。

pandas逆引き 早見表

やりたいこと 主なコード No.
CSV・Excelを読む/書く pd.read_csv to_csv(index=False) pd.read_excel pd.ExcelWriter 1〜7
文字化けを防ぐ 読む encoding="cp932"/Excel向けに書く encoding="utf-8-sig" 1, 4
中身をざっと見る head tail shape columns value_counts 8〜10
列・行を選ぶ df["列"] df[["列1","列2"]] loc(名前)iloc(番号)at drop rename 11〜17
条件で絞る・書き換える df[条件] & | ~ isin between query str.contains loc[条件, 列] = 18〜24
並べ替える・上位N件 sort_values nlargest nsmallest 25〜27
欠損値を扱う isna().sum() dropna(subset=) fillna({列: 値}) ffill 28〜32
型を変える astype astype("Int64") pd.to_numeric(errors="coerce") 33〜35
列を足す・計算する df["新列"] = 式 assign pd.col np.where np.select map cut 36〜42
文字列を加工する str.strip str.split(expand=True) str.replace str.extract str.zfill 43〜47
日付を扱う pd.to_datetime .dt.year .dt.day_name() pd.Timedelta resample 48〜52
集計する groupby().agg() 名前=("列","関数") transform size nunique 53〜58
縦横を変える pivot_table crosstab melt pivot 59〜62
表をつなぐ merge(on=, how=) pd.concat 63〜65
重複を扱う duplicated drop_duplicates(subset=, keep=) 66〜68
順位・前行との差・移動平均 rank cumcount shift diff rolling cumsum 69〜75
関数を当てる・変換する apply(axis=1) DataFrame.map itertuples pipe to_dict to_sql 76〜81

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「pandasの使い方 逆引き81選|pandas 3.0の実行結果つき」

動かす前の準備(バージョンとサンプルデータ)

pandasは pip install pandas で入ります。Excelを扱うときは openpyxl も入れます。

pip install pandas openpyxl
python -c "import pandas as pd; print(pd.__version__)"
# 3.0.6

pandas 3.0 は Python 3.11 以上が必要です。以降のコードは、すべて次のサンプル(注文データ6行、qty に欠損が1つ)を作った直後から実行しています。各コードブロックは、このサンプルを作り直してから実行した結果です。

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "order_id": [101, 102, 103, 104, 105, 106],
    "date": ["2026-04-01", "2026-04-01", "2026-04-02",
             "2026-04-03", "2026-04-03", "2026-04-05"],
    "member": ["sato", "suzuki", "sato", "takahashi", "suzuki", "tanaka"],
    "item": ["note", "pen", "pen", "file", "note", "pen"],
    "qty": [3, 10, 5, np.nan, 2, 8],
    "price": [120, 80, 80, 300, 120, 80],
})
print(df)
#    order_id        date     member  item   qty  price
# 0       101  2026-04-01       sato  note   3.0    120
# 1       102  2026-04-01     suzuki   pen  10.0     80
# 2       103  2026-04-02       sato   pen   5.0     80
# 3       104  2026-04-03  takahashi  file   NaN    300
# 4       105  2026-04-03     suzuki  note   2.0    120
# 5       106  2026-04-05     tanaka   pen   8.0     80

pandas 3.0で変わった書き方(置き換え表と実際の警告)

pandas 2.x 向けに書かれたコードが動かないときは、まずこの表を確認してください。左の書き方は pandas 3.0.6 で実行すると右のエラー・結果になります。

以前の書き方 pandas 3.0での結果 置き換え
df.append(行) AttributeError(2.0で削除) pd.concat([df, new], ignore_index=True)(No.65)
df.applymap(f) AttributeError df.map(f)(No.77)
df.fillna(method="ffill") TypeError(引数がない) df.ffill() / df.bfill()
df[条件]["列"] = 値(連鎖代入) ChainedAssignmentError 警告、元は変わらない df.loc[条件, "列"] = 値(No.24)
df["列"].fillna(0, inplace=True) 同じ警告、元は変わらない df["列"] = df["列"].fillna(0)
s = df["列"]; s.iloc[0] = 99 元の df は変わらない(2.xでは変わった) df.loc[0, "列"] = 99
文字列の列の型 object str 型になる 判定は pd.api.types.is_string_dtype
groupby(..., axis=1) TypeError df.T.groupby(...) などで向きを変える

実際に動かした結果です。

import pandas as pd
import numpy as np

df = pd.DataFrame({"item": ["note", "pen", "file"], "qty": [3, 10, np.nan]})

try:
    df.append({"item": "pen", "qty": 1}, ignore_index=True)
except AttributeError as e:
    print("AttributeError:", e)

df[df["item"] == "pen"]["qty"] = 0      # 連鎖代入
print(df["qty"].tolist())
AttributeError: 'DataFrame' object has no attribute 'append'
dep2.py:11: ChainedAssignmentError: A value is being set on a copy of a DataFrame or Series through chained assignment.
Such chained assignment never works to update the original DataFrame or Series, because the intermediate object on which we are setting values always behaves as a copy (due to Copy-on-Write).

Try using '.loc[row_indexer, col_indexer] = value' instead, to perform the assignment in a single step.

See the documentation for a more detailed explanation: https://pandas.pydata.org/pandas-docs/stable/user_guide/copy_on_write.html#chained-assignment
  df[df["item"] == "pen"]["qty"] = 0      # 連鎖代入
[3.0, 10.0, nan]

(ファイルのパスだけ短くしています。)

qty は10のままです。pandas 2.x では同じコードで SettingWithCopyWarning が出ていましたが、3.0 では Copy-on-Write(取り出した一部は常に「コピー」として振る舞い、書き換えが元に伝わらない仕組み)が既定になり、警告名も変わりました。値を書き換えるときは df.loc[行, 列] = 値 の1回で書くのが正解です。

同じコードを pandas 2.3.3 と 3.0.6 で比べると、違いがはっきりします。

df = pd.DataFrame({"item": ["note", "pen", "file"], "qty": [3, 10, np.nan]})
print(df.dtypes.astype(str).to_dict())
s = df["qty"]
s.iloc[0] = 99
print(df["qty"].tolist())
try:
    df.loc[0, "item"] = 123
    print("代入できた")
except TypeError as e:
    print("TypeError:", e)
出力 pandas 2.3.3 pandas 3.0.6
文字列列の型 {'item': 'object', ...} {'item': 'str', ...}
s.iloc[0] = 99 のあとの df["qty"] SettingWithCopyWarning が出て [99.0, 10.0, nan](元も変わる) [3.0, 10.0, nan](元は変わらない)
str 列に数値を代入 代入できた TypeError: Invalid value '123' for dtype 'str'. Value should be a string or missing value, got 'int' instead.

str 型の列には文字列と欠損値しか入りません。数値も入れたいときは df["item"] = df["item"].astype(object) で型を戻すか、str(123) で文字列にしてから入れます。なお str 型は PyArrow が入っていればPyArrow、なければPythonの文字列で保持されます(今回の環境は後者で StringDtype(storage='python') と表示されます)。

読み込み・書き出し(CSV・Excel・文字コード)

# ▼1. CSVに書き出す(Excel向けBOM付き)
df.to_csv("orders.csv", index=False, encoding="utf-8-sig")
# ▼2. CSVを読み込む
orders = pd.read_csv("orders.csv")
print(orders.head(2))
#    order_id        date  member  item   qty  price
# 0       101  2026-04-01    sato  note   3.0    120
# 1       102  2026-04-01  suzuki   pen  10.0     80
# ▼3. 列・型・日付を指定して読む
orders = pd.read_csv("orders.csv", usecols=["order_id", "date", "qty"],
                     dtype={"order_id": "string"}, parse_dates=["date"])
print(orders.dtypes.astype(str).to_dict())
# {'order_id': 'string', 'date': 'datetime64[us]', 'qty': 'float64'}
# ▼4. Shift_JIS(cp932)のCSVを読み書き
jp = pd.DataFrame({"品名": ["ノート", "ペン"], "数量": [3, 10]})
jp.to_csv("jp.csv", index=False, encoding="cp932")
try:
    pd.read_csv("jp.csv")  # 既定はUTF-8
except UnicodeDecodeError as e:
    print("UnicodeDecodeError:", str(e)[:48])
print(pd.read_csv("jp.csv", encoding="cp932"))
# UnicodeDecodeError: 'utf-8' codec can't decode byte 0x95 in position
#     品名  数量
# 0  ノート   3
# 1   ペン  10
# ▼5. Excelに複数シートで書き出す
with pd.ExcelWriter("orders.xlsx") as w:  # 要 openpyxl
    df.to_excel(w, sheet_name="orders", index=False)
    df.groupby("item")["qty"].sum().to_excel(w, sheet_name="by_item")
# ▼6. Excelをシート指定で読む
print(pd.read_excel("orders.xlsx", sheet_name=None).keys())
# dict_keys(['orders', 'by_item'])
# ▼7. 大きいCSVを分けて読む
for chunk in pd.read_csv("orders.csv", chunksize=4):
    print(len(chunk), chunk["order_id"].tolist())
# 4 [101, 102, 103, 104]
# 2 [105, 106]

データの中身を確認する

# ▼8. 先頭・末尾を見る
print(df.tail(1))
#    order_id        date  member item  qty  price
# 5       106  2026-04-05  tanaka  pen  8.0     80
# ▼9. 行数・列数・列名
print(df.shape, df.columns.tolist())
# (6, 6) ['order_id', 'date', 'member', 'item', 'qty', 'price']
# ▼10. 値ごとの件数
print(df["item"].value_counts().to_dict())
# {'pen': 3, 'note': 2, 'file': 1}

行・列を選択する

loc は名前(行ラベル・列名)、iloc は番号で選びます。

# ▼11. 1列(Series)
print(df["member"].head(2))
# 0      sato
# 1    suzuki
# Name: member, dtype: str
# ▼12. 複数列(DataFrame)
print(df[["member", "qty"]].head(2))
#    member   qty
# 0    sato   3.0
# 1  suzuki  10.0
# ▼13. 行番号で選ぶ
print(df.iloc[1:3, 0:3])
#    order_id        date  member
# 1       102  2026-04-01  suzuki
# 2       103  2026-04-02    sato
# ▼14. ラベルで選ぶ
print(df.loc[[0, 2], ["order_id", "item"]])
#    order_id  item
# 0       101  note
# 2       103   pen
# ▼15. 1セルの値
print(df.at[1, "member"], df.iat[1, 4])
# suzuki 10.0
# ▼16. 列を削除
print(df.drop(columns=["date", "price"]).columns.tolist())
# ['order_id', 'member', 'item', 'qty']
# ▼17. 列名を変更
print(df.rename(columns={"qty": "数量"}).columns.tolist())
# ['order_id', 'date', 'member', 'item', '数量', 'price']

条件で抽出する

条件を &(かつ)|(または)でつなぐときは、1つずつ括弧で囲みます。and or は使えません。

# ▼18. 条件1つ
print(df[df["qty"] >= 5][["order_id", "member", "qty"]])
#    order_id  member   qty
# 1       102  suzuki  10.0
# 2       103    sato   5.0
# 5       106  tanaka   8.0
# ▼19. AND・OR・NOT
print(df[(df["item"] == "pen") & (df["qty"] > 5)]["order_id"].tolist())
print(df[(df["item"] == "file") | ~(df["price"] < 120)]["order_id"].tolist())
# [102, 106]
# [101, 104, 105]
# ▼20. いずれかに一致(IN)
print(df[df["member"].isin(["sato", "tanaka"])]["order_id"].tolist())
# [101, 103, 106]
# ▼21. 範囲(BETWEEN)
print(df[df["qty"].between(3, 8)]["order_id"].tolist())
# [101, 103, 106]
# ▼22. 文字列で条件を書く
limit = 5
print(df.query("item == 'pen' and qty >= @limit")["order_id"].tolist())
# [102, 103, 106]
# ▼23. 部分一致(LIKE)
print(df[df["member"].str.contains("su")]["order_id"].tolist())
# [102, 105]
# ▼24. 条件に合う行の値を書き換える
df.loc[df["item"] == "pen", "price"] = 90
print(df["price"].tolist())
# [120, 90, 90, 300, 120, 90]

並び替え・上位N件

# ▼25. 降順に並べ替え
print(df.sort_values("qty", ascending=False)[["order_id", "qty"]].head(2))
#    order_id   qty
# 1       102  10.0
# 5       106   8.0
# ▼26. 複数列で並べ替え
print(df.sort_values(["item", "qty"], ascending=[True, False])["order_id"].tolist())
# [104, 101, 105, 102, 106, 103]
# ▼27. 上位N件・下位N件
print(df.nlargest(2, "qty")["order_id"].tolist(), df.nsmallest(1, "qty")["order_id"].tolist())
# [102, 106] [105]

欠損値(NaN)を扱う

まず isna().sum() で欠損の数を見てから、削除するか埋めるかを決めます。

# ▼28. 列ごとの欠損数
print(df.isna().sum().to_dict())
# {'order_id': 0, 'date': 0, 'member': 0, 'item': 0, 'qty': 1, 'price': 0}
# ▼29. 欠損のある行を抽出
print(df[df["qty"].isna()])
#    order_id        date     member  item  qty  price
# 3       104  2026-04-03  takahashi  file  NaN    300
# ▼30. 欠損のある行を削除
print(df.dropna(subset=["qty"]).shape)
# (5, 6)
# ▼31. 列ごとに値で埋める
print(df.fillna({"qty": 0})["qty"].tolist())
# [3.0, 10.0, 5.0, 0.0, 2.0, 8.0]
# ▼32. 平均・前の値で埋める
print(df["qty"].fillna(df["qty"].mean()).tolist())
print(df["qty"].ffill().tolist())
# [3.0, 10.0, 5.0, 5.6, 2.0, 8.0]
# [3.0, 10.0, 5.0, 5.0, 2.0, 8.0]

型を変換する

# ▼33. 型を変える
print(df["order_id"].astype(str).dtype, df["price"].astype(float).dtype)
# str float64
# ▼34. 欠損を含む整数列
print(df["qty"].astype("Int64").tolist())
# [3, 10, 5, <NA>, 2, 8]
# ▼35. 変換できない値はNaNにする
print(pd.to_numeric(pd.Series(["10", "abc", ""]), errors="coerce").tolist())
# [10.0, nan, nan]

列を追加・計算する

# ▼36. 列同士の計算で列を追加
df["amount"] = df["qty"] * df["price"]
print(df[["qty", "price", "amount"]].head(2))
#     qty  price  amount
# 0   3.0    120   360.0
# 1  10.0     80   800.0
# ▼37. 元を変えずに列を追加
print(df.assign(tax=lambda d: d["price"] * 0.1)["tax"].tolist())
# [12.0, 8.0, 8.0, 30.0, 12.0, 8.0]
# ▼38. pd.colで列を追加(3.0+)
print(df.assign(t=pd.col("qty") * pd.col("price"))["t"].tolist())
# [360.0, 800.0, 400.0, nan, 240.0, 640.0]
# ▼39. 条件で2つに振り分け(IF)
print(np.where(df["qty"] >= 5, "L", "S").tolist())
# ['S', 'L', 'L', 'S', 'S', 'L']
# ▼40. 3つ以上に振り分け(CASE WHEN)
print(np.select([df["qty"] >= 8, df["qty"] >= 3], ["A", "B"], default="C").tolist())
# ['B', 'A', 'B', 'C', 'C', 'A']
# ▼41. 辞書で値を置き換え
print(df["item"].map({"note": "ノート", "pen": "ペン", "file": "ファイル"}).tolist())
print(df["item"].replace({"pen": "ballpen"}).tolist())
# ['ノート', 'ペン', 'ペン', 'ファイル', 'ノート', 'ペン']
# ['note', 'ballpen', 'ballpen', 'file', 'note', 'ballpen']
# ▼42. 数値を区間に分ける
print(pd.cut(df["qty"], bins=[0, 3, 6, 10], labels=["少", "中", "多"]).tolist())
# ['少', '多', '中', nan, '少', '多']

文字列を操作する

# ▼43. 前後の空白削除・小文字化
print(pd.Series([" Note ", "PEN"]).str.strip().str.lower().tolist())
# ['note', 'pen']
# ▼44. 区切って列に分ける
print(df["date"].str.split("-", expand=True).head(2))
#       0   1   2
# 0  2026  04  01
# 1  2026  04  01
# ▼45. 置換(正規表現も可)
print(pd.Series(["A-01", "B-12"]).str.replace(r"\d+", "#", regex=True).tolist())
# ['A-#', 'B-#']
# ▼46. 正規表現で取り出す
print(pd.Series(["A-01", "B-12"]).str.extract(r"([A-Z])-(\d+)"))
#    0   1
# 0  A  01
# 1  B  12
# ▼47. 列をつなげる・ゼロ埋め
print((df["member"] + ":" + df["item"]).head(2).tolist())
print(df["order_id"].astype(str).str.zfill(6).head(2).tolist())
# ['sato:note', 'suzuki:pen']
# ['000101', '000102']

日付を扱う

# ▼48. 文字列を日付型に
df["date"] = pd.to_datetime(df["date"])
print(df["date"].dtype)
# datetime64[us]
# ▼49. 年・月・曜日を取り出す
print(df["date"].dt.month.tolist(), df["date"].dt.day_name().head(2).tolist())
# [4, 4, 4, 4, 4, 4] ['Wednesday', 'Wednesday']
# ▼50. 期間で絞り込む
print(df[(df["date"] >= "2026-04-02") & (df["date"] < "2026-04-04")]["order_id"].tolist())
# [103, 104, 105]
# ▼51. 日付の差・日数を足す
print((df["date"] - df["date"].min()).dt.days.tolist())
print((df["date"] + pd.Timedelta(days=7)).dt.strftime("%m/%d").head(2).tolist())
# [0, 0, 1, 2, 2, 4]
# ['04/08', '04/08']
# ▼52. 日ごとに集計(抜けた日も出す)
print(df.set_index("date").resample("D")["qty"].sum())
# date
# 2026-04-01    13.0
# 2026-04-02     5.0
# 2026-04-03     2.0
# 2026-04-04     0.0
# 2026-04-05     8.0
# Freq: D, Name: qty, dtype: float64

集計する(groupby・agg)

# ▼53. グループごとの合計
print(df.groupby("item")["qty"].sum().to_dict())
# {'file': 0.0, 'note': 5.0, 'pen': 23.0}
# ▼54. 複数の集計を一度に
print(df.groupby("item")["qty"].agg(["sum", "mean", "count"]).round(1))
#        sum  mean  count
# item
# file   0.0   NaN      0
# note   5.0   2.5      2
# pen   23.0   7.7      3
# ▼55. 集計列に名前を付ける
print(df.groupby("member", as_index=False).agg(
    orders=("order_id", "count"), qty_total=("qty", "sum")))
#       member  orders  qty_total
# 0       sato       2        8.0
# 1     suzuki       2       12.0
# 2  takahashi       1        0.0
# 3     tanaka       1        8.0
# ▼56. 件数・ユニーク数
print(df.groupby("item").size().to_dict(), df.groupby("item")["member"].nunique().to_dict())
# {'file': 1, 'note': 2, 'pen': 3} {'file': 1, 'note': 2, 'pen': 3}
# ▼57. 集計値を元の行に戻す
df["share"] = (df["qty"] / df.groupby("item")["qty"].transform("sum")).round(2)
print(df[["item", "qty", "share"]].head(3))
#    item   qty  share
# 0  note   3.0   0.60
# 1   pen  10.0   0.43
# 2   pen   5.0   0.22
# ▼58. 集計後に絞る(HAVING)
g = df.groupby("member")["qty"].sum()
print(g[g >= 8].to_dict())
# {'sato': 8.0, 'suzuki': 12.0, 'tanaka': 8.0}

ピボット・縦横変換

# ▼59. ピボットテーブル
print(df.pivot_table(index="member", columns="item", values="qty",
                     aggfunc="sum", fill_value=0))
# item       file  note   pen
# member
# sato        0.0   3.0   5.0
# suzuki      0.0   2.0  10.0
# takahashi   0.0   0.0   0.0
# tanaka      0.0   0.0   8.0
# ▼60. クロス集計(件数)
print(pd.crosstab(df["member"], df["item"]).head(2))
# item    file  note  pen
# member
# sato       0     1    1
# suzuki     0     1    1
# ▼61. 横持ち→縦持ち
wide = pd.DataFrame({"member": ["sato", "suzuki"], "4月": [3, 12], "5月": [5, 0]})
long = wide.melt(id_vars="member", var_name="month", value_name="qty")
print(long)
#    member month  qty
# 0    sato    4月    3
# 1  suzuki    4月   12
# 2    sato    5月    5
# 3  suzuki    5月    0
# ▼62. 縦持ち→横持ち
print(long.pivot(index="member", columns="month", values="qty"))
# month   4月  5月
# member
# sato     3   5
# suzuki  12   0

結合する(merge・concat)

indicator=True を付けると、結合できなかった行(left_only)がすぐわかります。

teams = pd.DataFrame({"member": ["sato", "suzuki", "yamada"], "team": ["A", "B", "C"]})
# ▼63. キーで内部結合(INNER JOIN)
print(df.merge(teams, on="member")[["order_id", "member", "team"]].head(3))
#    order_id  member team
# 0       101    sato    A
# 1       102  suzuki    B
# 2       103    sato    A
# ▼64. 左外部結合+結合結果の確認
m = df.merge(teams, on="member", how="left", indicator=True)
print(m[["order_id", "team", "_merge"]].tail(3))
#    order_id team     _merge
# 3       104  NaN  left_only
# 4       105    B       both
# 5       106  NaN  left_only
# ▼65. 行を追加(appendの代わり)
new = pd.DataFrame([{"order_id": 107, "member": "sato", "item": "file", "qty": 1, "price": 300}])
print(pd.concat([df, new], ignore_index=True).tail(2))
#    order_id        date  member  item  qty  price
# 5       106  2026-04-05  tanaka   pen  8.0     80
# 6       107         NaN    sato  file  1.0    300

重複を扱う

# ▼66. 重複を見つける
print(df.duplicated(subset=["member"]).tolist())
# [False, False, True, False, True, False]
# ▼67. 重複をすべて表示
print(df[df.duplicated(subset=["member"], keep=False)]["order_id"].tolist())
# [101, 102, 103, 105]
# ▼68. 重複を削除(最後を残す)
print(df.drop_duplicates(subset=["member"], keep="last")["order_id"].tolist())
# [103, 104, 105, 106]

ランキング・ウィンドウ関数

# ▼69. 順位(RANK)
print(df["qty"].rank(ascending=False, method="min").tolist())
# [4.0, 1.0, 3.0, nan, 5.0, 2.0]
# ▼70. グループ内連番(ROW_NUMBER)
print((df.groupby("item").cumcount() + 1).tolist())
# [1, 1, 2, 1, 2, 3]
# ▼71. グループ内順位
print(df.groupby("item")["qty"].rank(ascending=False).tolist())
# [1.0, 1.0, 3.0, nan, 2.0, 2.0]
# ▼72. グループごとに上位1件
print(df.sort_values("qty", ascending=False).groupby("item").head(1)[["item", "order_id", "qty"]])
#    item  order_id   qty
# 1   pen       102  10.0
# 0  note       101   3.0
# 3  file       104   NaN
# ▼73. 移動平均
print(df["price"].rolling(window=3).mean().round(1).tolist())
# [nan, nan, 93.3, 153.3, 166.7, 166.7]
# ▼74. 前の行との差・増減率(LAG)
s = pd.Series([100, 120, 90, 135])
print(pd.DataFrame({"v": s, "prev": s.shift(1), "diff": s.diff(), "pct": s.pct_change().round(2)}))
#      v   prev  diff   pct
# 0  100    NaN   NaN   NaN
# 1  120  100.0  20.0  0.20
# 2   90  120.0 -30.0 -0.25
# 3  135   90.0  45.0  0.50
# ▼75. グループごとの累積和
print(df.groupby("member")["qty"].cumsum().tolist())
# [3.0, 10.0, 8.0, nan, 12.0, 8.0]

apply・ループ・変換

# ▼76. 行ごとに関数を適用
print(df.apply(lambda r: f"{r['member']}-{r['item']}", axis=1).head(2).tolist())
# ['sato-note', 'suzuki-pen']
# ▼77. 全セルに関数を適用
print(df[["qty", "price"]].map(lambda v: f"{v:,.0f}").head(2))
#   qty price
# 0   3   120
# 1  10    80
# ▼78. 1行ずつループ
for row in df.head(2).itertuples(index=False):
    print(row.order_id, row.member, row.qty)
# 101 sato 3.0
# 102 suzuki 10.0
# ▼79. 処理をつなげる
def add_amount(d):
    return d.assign(amount=d["qty"] * d["price"])
print(df.pipe(add_amount).dropna().groupby("item")["amount"].sum().to_dict())
# {'note': 600.0, 'pen': 1840.0}
# ▼80. 辞書のリスト・リストに変換
print(df.head(2)[["order_id", "qty"]].to_dict(orient="records"))
print(df["item"].unique().tolist())
# [{'order_id': 101, 'qty': 3.0}, {'order_id': 102, 'qty': 10.0}]
# ['note', 'pen', 'file']
# ▼81. SQLで読む・テーブルに書く
import sqlite3
con = sqlite3.connect(":memory:")
df.to_sql("orders", con, index=False)
print(pd.read_sql("SELECT item, SUM(qty) AS qty FROM orders GROUP BY item", con))
#    item   qty
# 0  file   NaN
# 1  note   5.0
# 2   pen  23.0

SQLとpandasの対応表

SQLに慣れている人は、この表で対応を探すと早いです。

SQL pandas No.
SELECT a, b df[["a", "b"]] 12
WHERE qty >= 5 AND ... df[(条件1) & (条件2)] / df.query("...") 18, 19, 22
WHERE x IN (...) / BETWEEN / LIKE isin / between / str.contains 20, 21, 23
ORDER BY qty DESC sort_values("qty", ascending=False) 25
LIMIT 2 head(2) / nlargest(2, "qty") 8, 27
SELECT DISTINCT drop_duplicates() / unique() 68, 80
GROUP BY ... SUM() groupby("item")["qty"].sum() 53
COUNT(*) / COUNT(DISTINCT x) size() / nunique() 56
HAVING SUM(qty) >= 8 集計結果 g[g >= 8] 58
CASE WHEN ... END np.where / np.select 39, 40
INNER JOIN / LEFT JOIN merge(how="inner") / merge(how="left") 63, 64
UNION ALL / INSERT pd.concat([...], ignore_index=True) 65
UPDATE ... SET ... WHERE df.loc[条件, "列"] = 値 24
ROW_NUMBER() OVER (PARTITION BY) groupby().cumcount() + 1 70
RANK() OVER (ORDER BY) rank(method="min") 69
LAG(x) shift(1) 74
SUM(x) OVER (PARTITION BY) groupby().transform("sum") 57

1点だけ挙動が違います。No.53 と No.81 を見比べると、qty がすべて欠損の file グループは、pandasの sum() では 0.0、SQLの SUM() では NULL(読み込むと NaN)です。欠損だけのグループを欠損のままにしたいときは groupby("item")["qty"].sum(min_count=1) と書きます。

よくある質問

Q. SettingWithCopyWarning の対処法を調べたのに、警告が出ません。 A. pandas 3.0 でこの警告は廃止され、連鎖代入には ChainedAssignmentError が出るようになりました。どちらの場合も、df.loc[条件, "列"] = 値 の1回で書くのが解決策です。

Q. loc と iloc はどちらを使えばよいですか? A. 列名や条件で選ぶなら loc、何番目かで選ぶなら iloc です。loc[0:2] は2を含み、iloc[0:2] は2を含まない点に気をつけます。並べ替えのあとなど行名が番号とずれたときは、reset_index(drop=True) で振り直すと扱いやすくなります。

Q. apply は遅いと聞きました。使ってはいけませんか? A. 使ってかまいません。ただ、列同士の四則演算(No.36)や np.where(No.39)のような「列ごとにまとめて計算する書き方」のほうが速く、行数が多いと差が大きくなります。まずまとめて書けないかを考え、どうしても行ごとの処理が必要なときに apply(axis=1) を使うのがおすすめです。

Q. pandas 2.x のままのプロジェクトでも、この記事のコードは使えますか? A. はい。81項目すべてを pandas 2.3.3 でも実行し、No.38 の pd.col(3.0で追加、2.3.3では AttributeError)以外は同じ結果になることを確認しました。違いは表示だけで、文字列の列が object、日付が datetime64[ns](3.0は datetime64[us])と出ます。

まとめ

  • pandasの操作は「選ぶ(loc/iloc)→ 絞る(条件)→ まとめる(groupby/pivot_table)→ つなぐ(merge/concat)」の4つでほとんど表せる
  • CSVの文字化けは読み込み encoding="cp932"、Excel向け書き出し encoding="utf-8-sig" で解決できる
  • 条件は & | ~ と括弧、複数値は isin、範囲は between
  • pandas 3.0 は Copy-on-Write が既定。書き換えは df.loc[条件, "列"] = 値 の1回で
  • append は pd.concat、applymap は DataFrame.map、fillna(method=) は ffill に置き換える
  • 文字列の列は str 型になり、文字列と欠損値だけが入る
  • SQLの GROUP BY・JOIN・ROW_NUMBER も groupby・merge・cumcount で書ける

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「pandasの使い方 逆引き81選|pandas 3.0の実行結果つき」

株式会社RJCでは、データを読み解き、確かめながら形にする力を、プロジェクトの中で仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?