Menu
CoddyTech

pandas チートシート

最終更新

DataFrame を作る

例やテスト、参照用テーブルのために手で作る小さな DataFrame です。

やりたいことコード
pandas と NumPy をインポートimport pandas as pd import numpy as np
列の辞書から作成df = pd.DataFrame({"name": ["Ada", "Ben"], "age": [36, 28]})
行のリストから作成pd.DataFrame([{"name": "Ada", "age": 36}, {"name": "Ben", "age": 28}])
NumPy 配列から作成pd.DataFrame(np.arange(6).reshape(3, 2), columns=["x", "y"])
ラベル付きの Seriess = pd.Series([3, 5, 2], index=["a", "b", "c"])
日付の範囲pd.date_range("2026-01-01", periods=7, freq="D")

ファイルの読み書き

1回の呼び出しでファイルを DataFrame に読み込み、1回の呼び出しで書き出せます。

やりたいことコード
CSV ファイルを読み込むdf = pd.read_csv("sales.csv")
一部の列だけ、日付は日付型でpd.read_csv("sales.csv", usecols=["date", "city", "sales"], parse_dates=["date"])
列をインデックスにするpd.read_csv("sales.csv", index_col="id")
タブなど別の区切り文字pd.read_csv("sales.tsv", sep="\t")
特定の記号も欠損値として扱うpd.read_csv("sales.csv", na_values=["n/a", "-"])
先頭の行だけ読み込むpd.read_csv("sales.csv", nrows=1000)
Excel シートを読み込む (openpyxl が必要)pd.read_excel("report.xlsx", sheet_name="2026")
JSON レコードを読み込むpd.read_json("records.json")
SQL データベースから読み込むpd.read_sql("SELECT * FROM orders", conn)
インデックスなしで CSV に書き出すdf.to_csv("clean.csv", index=False)
Excel や Parquet に書き出すdf.to_excel("clean.xlsx", index=False), df.to_parquet("clean.parquet")

データを確認する

新しいデータセットを手にしたら、まず実行する呼び出しです。

やりたいことコード
先頭と末尾の行df.head(), df.tail(3)
行数と列数df.shape # (6, 7)
列の型と非欠損数df.info()
数値列の要約統計量df.describe()
全列の要約df.describe(include="all")
列名と型df.columns, df.dtypes
値ごとの件数df["city"].value_counts()
値ごとの割合df["city"].value_counts(normalize=True)
ユニークな値とその数df["city"].unique(), df["city"].nunique()
列ごとの欠損値の数df.isna().sum()
行をランダムに抽出df.sample(3, random_state=0)
数値列の相関df.corr(numeric_only=True)

列と行を選択する

loc はラベルで選択し、スライスの終端を含みます。iloc は位置で選択し、終端を含みません。

やりたいことコード
1列を Series としてdf["age"]
複数列を DataFrame としてdf[["name", "age"]]
ラベルで行と列を指定df.loc[0:2, ["name", "age"]]
位置で行と列を指定df.iloc[0:2, 0:3]
1つの値df.at[0, "age"], df.iat[0, 3]
最後の行df.iloc[-1]
特定の型の列df.select_dtypes(include="number")
文字列の列 (pandas 3)df.select_dtypes(include="str")
列名のパターンで選択df.filter(like="sal"), df.filter(regex="^(age|salary)$")
列の値で行を引くdf.set_index("name").loc["Ada", "salary"]
0, 1, 2 のインデックスに戻すdf.reset_index(drop=True)
列や行を削除df.drop(columns=["email"]), df.drop(index=[0, 1])

行をフィルタする

条件はそれぞれ括弧で囲み、& (かつ)、| (または)、~ (否定) で組み合わせます。

やりたいことコード
条件に合う行df[df["age"] > 30]
両方の条件df[(df["age"] > 30) & (df["city"] == "Oslo")]
どちらかの条件df[(df["city"] == "Oslo") | (df["salary"] > 6000)]
値がリストに含まれるdf[df["city"].isin(["Oslo", "Rome"])]
値がリストに含まれないdf[~df["city"].isin(["Oslo", "Rome"])]
2つの値の間 (両端を含む)df[df["age"].between(30, 40)]
クエリ文字列でフィルタdf.query("age > 30 and city == 'Oslo'")
クエリで変数を使うmin_age = 30 df.query("age > @min_age")
文字列を含むdf[df["name"].str.contains("e", case=False)]
欠損している値、していない値df[df["age"].isna()], df[df["age"].notna()]
行を絞って列を選ぶdf.loc[df["age"] > 30, ["name", "salary"]]
上位または下位 n 行df.nlargest(3, "salary"), df.nsmallest(2, "age")
重複する値を持つ行df[df.duplicated(subset=["city"], keep=False)]

並べ替えと順位

やりたいことコード
列で並べ替えdf.sort_values("salary")
大きい順df.sort_values("salary", ascending=False)
複数列で並べ替えdf.sort_values(["city", "salary"], ascending=[True, False])
欠損値を先頭にdf.sort_values("age", na_position="first")
インデックスで並べ替えdf.sort_index()
順位付け (最大値が1位)df["salary"].rank(ascending=False)

列の追加と変更

列全体をまとめて処理する操作は高速です。apply は組み込みメソッドで対応できないときだけ使いましょう。

やりたいことコード
他の列から新しい列df["bonus"] = df["salary"] * 0.1
メソッドチェーンの中で列を追加df.assign(bonus=lambda d: d["salary"] * 0.1)
条件で値を決めるdf["level"] = np.where(df["age"] >= 40, "senior", "junior")
複数の条件で値を決めるdf["band"] = np.select([df["age"] < 30, df["age"] < 45], ["young", "mid"], default="senior")
条件を満たす値を変更df.loc[df["city"] == "Lima", "salary"] = 4000
辞書で値を置き換えdf["country"] = df["city"].map({"Oslo": "NO", "Rome": "IT", "Lima": "PE"})
列に関数を適用df["salary"].apply(lambda x: round(x, -3))
全セルに関数を適用df[["age", "salary"]].map(lambda x: x / 1000)
列名を変更df.rename(columns={"salary": "pay"})
列の型を変更df["salary"].astype("float64")
文字列を数値に (不正値は NaN)pd.to_numeric(s, errors="coerce")
数値をラベル付きの区間に分けるpd.cut(df["age"], bins=[0, 30, 45, 120], labels=["young", "mid", "senior"])
数値を同じサイズのグループに分けるpd.qcut(df["salary"], q=4, labels=False)
行をループ (遅いので最終手段)for row in df.itertuples(): print(row.name, row.salary)

欠損値とクリーニング

数値の欠損は NaN、日付の欠損は NaT と表示されます。どの呼び出しも新しいオブジェクトを返すので、結果を代入してください。

やりたいことコード
列ごとの欠損値の割合df.isna().mean()
欠損値を含む行を削除df.dropna()
重要な列が欠損した行を削除df.dropna(subset=["age"])
列ごとの値で埋めるdf.fillna({"age": df["age"].median()})
前後の行の値で埋めるdf["age"].ffill(), df["age"].bfill()
補間で埋めるdf["age"].interpolate()
特定の記号を欠損値に変換df.replace(["n/a", "-", ""], np.nan)
重複行を削除df.drop_duplicates()
キーごとに最後の行を残すdf.drop_duplicates(subset=["city"], keep="last")
列名を整えるdf.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
外れ値を上限・下限で抑えるdf["salary"].clip(lower=4000, upper=6000)
繰り返しの多い文字列は category 型にdf["city"] = df["city"].astype("category")

文字列の列 (.str)

pandas 3 では文字列の列がデフォルトで str dtype になります。.str メソッドは列全体に作用し、欠損値は欠損値のまま残ります。

やりたいことコード
大文字、小文字、先頭大文字df["name"].str.upper(), df["name"].str.lower(), df["name"].str.title()
空白を除去df["name"].str.strip()
文字列を置換df["email"].str.replace("mail.com", "example.com")
正規表現で置換df["email"].str.replace(r"@.*", "", regex=True)
含む、で始まるdf["name"].str.contains("a"), df["name"].str.startswith("E")
各値の長さdf["name"].str.len()
先頭の数文字df["name"].str[:2]
分割して列にするdf["email"].str.split("@", expand=True)
正規表現のグループで抽出df["email"].str.extract(r"@(\w+)")
文字列の列を連結df["name"] + " (" + df["city"] + ")"
数値をゼロ埋めdf["salary"].astype("str").str.zfill(6)
新しい文字列 dtypedf["name"].dtype # str

日付と時刻

.dt アクセサは datetime 型の列で使えます。並べ替えた日付インデックス (下の ts) があれば、文字列でのスライスやリサンプリングができます。

やりたいことコード
列を datetime に変換df["date"] = pd.to_datetime(df["date"])
書式を指定して変換pd.to_datetime(["03/01/2026", "15/01/2026"], format="%d/%m/%Y")
年、月、曜日名df["date"].dt.year, df["date"].dt.month, df["date"].dt.day_name()
日付を月単位にまとめるdf["date"].dt.to_period("M")
2つの日付の間の日数(pd.Timestamp("2026-12-31") - df["date"]).dt.days
日数や月数を足すdf["date"] + pd.Timedelta(days=30), df["date"] + pd.DateOffset(months=1)
期間内の行df[df["date"].between("2021-01-01", "2022-12-31")]
日付インデックスを文字列でスライスts = df.set_index("date").sort_index() ts.loc["2021":"2022"]
月ごとの合計ts["salary"].resample("ME").sum()
週ごとの平均 ("QE" は四半期、"YE" は年)ts["salary"].resample("W").mean()
移動平均ts["salary"].rolling(3).mean()
前の行からの変化ts["salary"].diff(), ts["salary"].pct_change()
値を1行下にずらすts["salary"].shift(1)
累積合計ts["salary"].cumsum()
タイムゾーンの設定と変換ts.index.tz_localize("UTC").tz_convert("Europe/Oslo")

グループ化と集計

groupby はキーで行を分割し、各グループに関数を適用して結果をまとめます。

やりたいことコード
グループごとの平均df.groupby("city")["salary"].mean()
複数の統計量を一度にdf.groupby("city")["salary"].agg(["mean", "max", "count"])
結果の列に名前を付けるdf.groupby("city").agg(avg_pay=("salary", "mean"), people=("name", "count"))
2つの列でグループ化df.groupby(["city", "team"])["salary"].sum()
キーを列として残すdf.groupby("city", as_index=False)["salary"].mean()
グループごとの行数df.groupby("city").size()
グループの結果を全行にdf["city_avg"] = df.groupby("city")["salary"].transform("mean")
一部のグループだけ残すdf.groupby("city").filter(lambda g: len(g) >= 2)
グループごとに最大値の行df.loc[df.groupby("city")["salary"].idxmax()]
グループごとの上位 n 行df.sort_values("salary", ascending=False).groupby("city").head(2)
グループ内で行に連番df.groupby("city").cumcount()
グループをループfor city, group in df.groupby("city"): print(city, len(group))
フィルタ、集計、並べ替えを1つのチェーンで(df.query("age > 30") .groupby("city", as_index=False) .agg(avg_pay=("salary", "mean")) .sort_values("avg_pay", ascending=False))

ピボットと変形

縦長 (long) のデータは1観測につき1行です。横長 (wide) のデータは1つの変数を複数の列に広げます。

やりたいことコード
ピボットテーブルdf.pivot_table(index="city", columns="team", values="salary", aggfunc="mean", fill_value=0)
合計付きのピボットテーブルdf.pivot_table(index="city", values="salary", aggfunc="sum", margins=True)
組み合わせを数えるpd.crosstab(df["city"], df["team"])
行ごとの割合pd.crosstab(df["city"], df["team"], normalize="index")
横長から縦長へlong = df.melt(id_vars="name", value_vars=["age", "salary"], var_name="field", value_name="value")
縦長から横長へlong.pivot(index="name", columns="field", values="value")
内側のインデックスを列へdf.groupby(["city", "team"])["salary"].sum().unstack(fill_value=0)
リストの要素ごとに1行pd.DataFrame({"id": [1, 2], "tags": [["a", "b"], ["c"]]}).explode("tags")
列を one-hot エンコードpd.get_dummies(df["team"], prefix="team")
行と列を入れ替えdf.T

DataFrame を結合する

concat はフレームを積み重ね、merge は SQL と同じようにキー列で結合します。

やりたいことコード
行を積み重ねるpd.concat([df_2025, df_2026], ignore_index=True)
横に並べるpd.concat([left, right], axis=1)
キー列で結合orders.merge(customers, on="customer_id", how="left")
結合の種類how="inner", "left", "right", "outer"
名前の違うキーorders.merge(users, left_on="customer_id", right_on="id")
結合を検証し各行の出所を記録orders.merge(customers, on="customer_id", how="left", validate="many_to_one", indicator=True)
インデックスで結合left.join(right, how="inner")
別のテーブルに一致しない行orders[~orders["customer_id"].isin(customers["customer_id"])]

pandas でグラフを描く

pandas は Matplotlib で描画します。どのプロット呼び出しも Matplotlib の ax を返すので、そのまま見た目を調整できます。

やりたいことコード
Series の折れ線グラフts["salary"].plot()
2つの列から折れ線グラフdf.plot(x="date", y="salary")
集計結果の棒グラフdf.groupby("city")["salary"].mean().plot.bar()
並べ替えた横棒グラフdf["city"].value_counts().sort_values().plot.barh()
ヒストグラムdf["salary"].plot.hist(bins=20)
散布図df.plot.scatter(x="age", y="salary")
グループごとの箱ひげ図df.boxplot(column="salary", by="city")
タイトルと軸ラベルax = df.plot(x="date", y="salary", title="Salary") ax.set_ylabel("EUR")
グラフを表示または保存plt.show(), ax.figure.savefig("salary.png", dpi=150)

pandas 3: 旧書式と今の書き方

古いチュートリアルからコピーしたコードは、pandas 3 ではエラーや警告になることがよくあります。代わりに pandas 3 の列の書き方を使いましょう。

やりたいことpandas 3旧書式
全セルに関数を適用df.map(f)df.applymap(f)
前の行の値で埋めるdf.ffill()df.fillna(method="ffill")
行を追加pd.concat([df, new_rows])df.append(new_rows)
月末でリサンプリングts["salary"].resample("ME").sum()resample("M")
1時間ごとの日付pd.date_range("2026-01-01", periods=24, freq="h")freq="H"
1つの値を設定df.loc[0, "age"] = 37df["age"][0] = 37
フィルタした部分を変更high = df[df["salary"] > 5000] high["salary"] = 0high = df[df["salary"] > 5000].copy()
文字列の列かどうかdf["name"].dtype == "str"df["name"].dtype == object

データ分析の現場で毎日使う pandas のコードを、タスク別にまとめました。データの作成と読み込み、中身の確認、行の選択とフィルタ、列の追加、欠損値の処理、文字列と日付の操作、グループ集計、変形、結合、グラフ描画まで揃っています。各行は貼り付けてすぐ使える短いコードと、その動作を説明する一文で構成されています。

すべて Coddy で動いている pandas 3 向けに書いています。文字列の列には新しい str dtype が使われ、Copy-on-Write は常に有効です。applymap や fillna(method=...) のように削除された API は、旧書式の表にだけ載せています。例では name、city、team、age、salary、date、email の列を持つ DataFrame df を使います。Python 自体が初めての方は Python チートシート と Python プレイグラウンド から始めて、NumPy、Matplotlib、scikit-learn のチートシートもあわせて手元に置いておきましょう。

pandas チートシートのよくある質問

この pandas チートシートは無料ですか?
はい。この pandas チートシートは完全無料で、登録も不要です。ブックマークするか、ブラウザから PDF に印刷しておけば、groupby、merge、ピボットテーブルの正確な書き方が必要なときにいつでも見返せます。
このチートシートはどの pandas バージョンに対応していますか?
pandas 3 です。文字列の列には新しい str dtype が使われ、Copy-on-Write は常に有効です。pandas 3 で削除された呼び出し (applymap、fillna(method=...)、append、頻度エイリアスの M と H) は最後の表にだけ載せ、代わりの書き方と並べています。str dtype や Copy-on-Write に依存する行を除けば、ほぼすべてのコードは pandas 2.2 でも動きます。
loc と iloc の違いは何ですか?
loc はラベル、つまりインデックスの値と列名で選択し、df.loc[0:2] のようなスライスは終端を含みます。iloc は Python のリストと同じく整数の位置で選択するので、df.iloc[0:2] は最初の2行を返し、終端は含みません。loc に条件を渡せば、行の絞り込みと列の選択を一度にできます: df.loc[df["age"] > 30, ["name"]]。
複数の条件で DataFrame をフィルタするには?
条件をそれぞれ括弧で囲み、かつは &、またはは |、否定は ~ でつなぎます: df[(df["age"] > 30) & (df["city"] == "Oslo")]。Python の and と or は列全体には使えません。長い条件なら df.query("age > 30 and city == 'Oslo'") のほうが読みやすくなります。
merge、join、concat の違いは何ですか?
merge は SQL の JOIN のようにキー列で2つの DataFrame を結合し、how="inner"、"left"、"right"、"outer" を指定できます。join はインデックスで結合するショートカットです。concat はキーをまったく照合せず、フレームを縦に積み重ねるか、axis=1 で横に並べます。
代入しても DataFrame が変わらないのはなぜですか?
pandas 3 以降は Copy-on-Write により、どの選択結果もコピーのように振る舞います。df["age"][0] = 37 のような連鎖代入は一時オブジェクトを変更するだけで、df はそのままです。代わりに loc の1回の呼び出しで書きましょう: df.loc[0, "age"] = 37。dropna や fillna などのメソッドも新しいオブジェクトを返すので、結果を代入してください。
pandas のコードをオンラインで実行できますか?
はい。無料の Matplotlib プレイグラウンド では、pandas、NumPy、Matplotlib、scikit-learn 入りの Python をブラウザで実行できるので、このチートシートのどのコードも貼り付けてすぐ試せます。インストールは不要です。Coddy の機械学習コースでは、最初の DataFrame からモデルに渡すデータまで、pandas を一歩ずつ学べます。
Coddyのプログラミング言語のイラスト

CoddyでPandasを学ぼう

始める