概要(pandas の列操作は「列名で考える」が合言葉)
pandas の列操作は「列名を軸」に発想すると迷いません。列の選択・追加・更新・削除・並べ替え・型変換・文字列処理・条件列の作成まで、ほぼ1〜2行で書けます。重要なのは「loc を使って明示的に列へ代入する」「型と欠損を最初に整える」「ベクトル化(配列計算)で速く書く」の3点です。これだけで、短く速く壊れない列操作が身につきます。
列の選択・追加・更新・削除(まずは核となる操作)
列の選択と複数列の取り出し
import pandas as pd
df = pd.DataFrame({"name": ["Alice", "Bob"], "age": [25, 30], "city": ["Tokyo", "Osaka"]})
df["age"] # 1列(Series)
df[["name", "age"]] # 複数列(DataFrame)
Python1列は Series(縦ベクトル)、複数列は DataFrame(表)として返ります。後工程が何を期待するかに合わせて取り出します。
列の追加と更新(ベクトル計算で一発)
df["age_plus"] = df["age"] + 1 # 計算で新列
df["tag"] = "user" # 全行に同じ値
df["name"] = df["name"].str.strip() # 文字列整形(前後空白除去)
Python既存列からの計算・定数の挿入・文字列処理は“列全体”に対して一度に適用できます(ループ不要)。
列の削除・列名の変更・列順の並べ替え
df = df.drop(columns=["age_plus"]) # 列削除
df = df.rename(columns={"city": "pref"}) # 列名変更
df = df[["name", "age", "pref"]] # 列順の固定
Python前処理の早い段階で列順・名前を固定すると、下流のコードが安定します。
条件列・マッピング・複数列計算(よく使う“意味付け”)
条件列の追加(真偽・カテゴリ)
df["adult"] = df["age"] >= 20 # True/False
df["age_band"] = pd.cut(df["age"], bins=[0,20,30,100], labels=["<=20","20-30","30+"])
Python条件から意味を持つ列(フラグや区分)を作るのが定番です。cut は連続値を区間へまとめます。
辞書マッピングで値を変換
map_city = {"Tokyo": "関東", "Osaka": "関西"}
df["region"] = df["pref"].map(map_city) # 該当しない値は NaN
Pythonマスタ変換は map が最短。未定義は NaN になるので必要なら fillna で補完します。
複数列からの計算(ベクトルで一気に)
sales = pd.DataFrame({"qty": [10, 8], "price": [350.0, 280.0]})
sales["amount"] = sales["qty"] * sales["price"]
Python列同士の四則演算はベクトル化され、高速で安全です。
apply とベクトル化の使い分け(遅くしない書き方)
まずは「ベクトル化(配列計算)」で書く
df["name_len"] = df["name"].str.len() # ベクトル化(速い)
Python文字列・日付・数値の多くは Series のアクセサ(str/dt)や演算でベクトル化できます。速度・可読性が高く、最優先。
apply は“複雑なロジック”に限定
def label(row):
if row["age"] >= 30 and row["pref"] == "Osaka":
return "VIP"
return "REG"
df["segment"] = df.apply(label, axis=1) # 行単位(遅め)
Python行単位の apply は柔軟ですが遅くなりがち。パターン化できるなら条件演算(& |)や np.where、map/cut を使ってベクトル化する方が良いです。
型と欠損(壊れない列操作の下地づくり)
型を固定して“曖昧さ”をなくす
df["age"] = df["age"].astype("Int64") # 欠損対応の整数型(Pandas 独自)
df["name"] = df["name"].astype("string") # 文字列型(新方式)
PythonInt64(頭大文字)は NaN を許容する整数型。型を決めると計算・比較の挙動が安定します。
不正値を安全に数値化(coerce で NaN)
import pandas as pd
raw = pd.DataFrame({"score": ["10", "20", "x"]})
raw["score"] = pd.to_numeric(raw["score"], errors="coerce") # "x" → NaN
Pythonto_numeric(errors=”coerce”) は“壊れた値”を NaN に落とし、次の処理へ進めます。
欠損の補完・除去の基本線
df["pref"] = df["pref"].fillna("不明") # 補完
df = df.dropna(subset=["age"]) # 必須列が欠損の行を落とす
Python“どの列が必須か”をはっきり決め、補完か削除かの方針を最初に統一します。
安全な代入と落とし穴(SettingWithCopyWarning を避ける)
loc で「明示的に」列へ代入する
sub = df.loc[df["age"] >= 25, ["name", "age"]] # ビュー/コピーの曖昧さがある
df.loc[df["age"] >= 25, "tag"] = "silver" # 元の df へ明示代入(安全)
Python“部分 DataFrame に代入”は警告の温床。元の df へ代入するなら df.loc[…] = … を使って明示してください。
連鎖インデックス(chained indexing)を避ける
# 悪い例:df[df["age"]>=25]["tag"] = "silver" ← 警告・反映されないことも
# 良い例:
df.loc[df["age"]>=25, "tag"] = "silver"
Python「条件で絞って、さらに列へ代入」を1行でやると曖昧になります。必ず loc で一発指定します。
例題で身につける(定番から一歩先まで)
例題1:列追加→整形→並べ替え
import pandas as pd
df = pd.DataFrame({"name": [" Alice ", "Bob", "Cathy"], "age": [25, 30, 22], "city": ["Tokyo", "Osaka", "Tokyo"]})
df["name"] = df["name"].str.strip() # 空白除去
df["adult"] = df["age"] >= 20 # フラグ列
df = df.sort_values(by=["age"], ascending=False)
print(df)
Python例題2:辞書マップ+カテゴリ化で意味づけ
import pandas as pd
df = pd.DataFrame({"city": ["Tokyo","Osaka","Nagoya"]})
region = {"Tokyo": "関東", "Osaka": "関西"}
df["region"] = df["city"].map(region).fillna("その他")
df["region"] = df["region"].astype("category") # カテゴリ型(軽量・集計向き)
print(df)
Python例題3:複数列の条件でセグメント列を作る(ベクトル化)
import numpy as np, pandas as pd
df = pd.DataFrame({"age":[18,25,35], "city":["Tokyo","Osaka","Tokyo"]})
df["seg"] = np.where((df["age"]>=30) & (df["city"]=="Tokyo"), "VIP", "REG")
print(df)
Python例題4:型と欠損を整えて安全に計算
import pandas as pd
df = pd.DataFrame({"qty": ["10", "x", "5"], "price": [350.0, 280.0, None]})
df["qty"] = pd.to_numeric(df["qty"], errors="coerce") # 不正値→NaN
df["price"] = pd.to_numeric(df["price"], errors="coerce") # None→NaN
df["amount"] = df["qty"] * df["price"] # 欠損があれば NaN
df["amount"] = df["amount"].fillna(0.0) # 補完ポリシー
print(df)
Pythonまとめ
pandas の列操作は「列名で考える」「loc で明示代入する」「型と欠損を先に整える」が基本線です。追加・更新・削除・並べ替えは1〜2行、条件列・マッピング・区分化は map / cut / np.where でベクトル化し、apply は本当に複雑なときだけ。SettingWithCopyWarning を避けるには chained indexing をやめて loc を使う。Int64/string/category などの型で曖昧さを減らせば、初心者でも短く・速く・壊れない列操作が自然に書けるようになります。
