この記事でわかること

  • 複数の列の条件から、区分の列を1回で作る方法(numpy.select)
  • 条件を並べる順番で結果が変わる理由と、並べ方の決まり
  • defaultを書き忘れたときや、&のまわりに括弧がないときのエラー
  • 金額が空の行の扱いと、自分の表で使う前に確かめること

「金額が10万円以上で東京なら最優先、10万円以上なら優先、5万円以上なら通常」のような区分を、ExcelのIFを何重にも入れ子にした式で付けていませんか。条件が増えるたびに式が読みにくくなります。この記事では、条件とラベルを上から順に並べて、numpy.selectで区分の列を作る手順を紹介します。

拠り所は、NumPy 2.5のnumpy.selectの説明と、pandas 3.1.0のユーザーガイドのデータの選び方の章です。どちらも2026年10月31日に原文を開いて確かめました。使った注文の表は、説明のためにこしらえた架空のデータです。

先に結論: 条件は細かいものから順に並べる

条件のリストとラベルのリストを同じ順に並べ、numpy.selectに渡します。 1つの行が複数の条件に当たるときは、リストの前にある条件の区分になります。そのため、細かい条件ほど上に書きます。

順番 条件 区分
1 10万円以上かつ東京 最優先
2 10万円以上 優先
3 5万円以上 通常
どれでもない (default) 対象外

numpy.selectのしくみ

numpy.selectは、条件の並び(condlist)に応じて、選ぶ値の並び(choicelist)から値を取り出した配列を返します。NumPyの資料では、複数の条件が満たされるときは、condlistで最初に出てくる条件が使われると説明しています。

choicelistは、condlistと同じ長さにします。どの条件も偽だった行には、defaultに渡した値が入ります。

pandasのユーザーガイドにも、新しい列を条件で作る例があります。2つの中から選ぶならnumpy.where、条件が複数あるならnumpy.selectを使えるとしています。

手順: 金額と地域から区分の列を作る

次のコードは、架空の注文の表 orders.xlsx の「金額」と「地域」から「区分」の列を作り、orders_labeled.xlsx という別の名前で保存します。読み込んだ orders.xlsx には書き込みません。

import numpy as np
import pandas as pd

# orders.xlsx を読み込む。結果は別の名前のファイルに書き出す
orders = pd.read_excel("orders.xlsx")

# 条件は上から順に判定する(先に当たった区分になる)
conditions = [
    (orders["金額"] >= 100000) & (orders["地域"] == "東京"),
    orders["金額"] >= 100000,
    orders["金額"] >= 50000,
]
labels = ["最優先", "優先", "通常"]
orders["区分"] = np.select(conditions, labels, default="対象外")
print(orders["区分"].value_counts())
print("金額が空の行:", orders["金額"].isna().sum())

orders.to_excel("orders_labeled.xlsx", index=False)

numpyはpandasと一緒に入ります。xlsxの読み書きにはopenpyxlも要ります。金額のしきい値や地域の名前は、自分の表の決まりに合わせて書き換えます。

試した結果

注文が6行だけの作り物の表で動かしました。地域と金額は、東京・12万円、大阪・15万円、東京・3万円、福岡・8万円、大阪・空欄、東京・6万円です。

  • 区分は上から順に、最優先・優先・対象外・通常・対象外・通常になりました
  • 大阪の15万円は「10万円以上かつ東京」に当たらず、2番目の「優先」になりました
  • 金額が空欄の大阪の行は、3万円の行と同じ「対象外」で、「金額が空の行: 1」と表示されました
  • 実行の前と後で orders.xlsx のハッシュ値を比べ、同じであることを確かめました

使ったのは、作業PC(Mac)のPython 3.12.15と、numpy 2.5.4・pandas 3.1.0・openpyxl 3.1.5です。書き出したファイルをExcelのアプリで開いて見てはいません。

自分で直すか、相談するかの判断

目安は、「区分の決まりを、上から順に当てはめる表にできるか」です。結論の表のように、順番・条件・区分を書き出せるなら、そのままコードの2つのリストになります。

決まりが部署の慣習で決まっていて、例外が多い場合は、先に決まりの表を作るところから始まります。どの順番で判定するかは、区分を使う人と表を見ながら決めます。決めた後は、区分ごとの件数を数えて、思ったとおりに分かれたかを確かめます。

つまずきやすいところ

  • 広い条件を先に書く: 試したときも、「5万円以上」を先頭に置くと、12万円と15万円の行まで「通常」になりました。細かい条件ほど上に書きます
  • defaultを書き忘れる: defaultは省くと0です。ラベルが文字のときに省くと、試したときは「Choicelist and default value do not have a common dtype」というTypeErrorで止まりました。文字のラベルなら、defaultにも文字を渡します
  • &のまわりの括弧を省く: pandasのユーザーガイドでは、&・|・~ で条件をつなぐときは括弧でまとめる必要があるとしています。括弧なしで書くと、試したときもTypeErrorになりました
  • 金額の範囲だけで区分を付けたい: 条件が1つの列の数値の範囲だけなら、PythonでExcelの数値を区切って範囲ごとの件数を数える手順のpd.cutのほうが短く書けます
  • 区分を付けずに行を取り出したい: 条件に合う行だけを残す方法は、PythonでExcelの表から条件に合う行を抽出する手順で紹介しています
  • 区分ごとに集計したい: 作った区分の列で件数や金額をまとめる方法は、PythonでExcelのピボットテーブルのように集計する手順にまとめています

まとめ

  • 条件のリストとラベルのリストを同じ順に並べ、numpy.selectに渡します
  • 複数の条件に当たる行は前の条件の区分になるので、細かい条件から書きます
  • 文字のラベルなら、defaultにも文字を渡します
  • &でつなぐ条件は、1つずつ括弧で囲みます