雑記 in hibernation

頭の整理と備忘録

Pandas dataframeでリストに含まれる要素であればTrueを返す

pythonのpandasにて、dataframe内のある要素が照合用のリストに含まれているかどうか確認したい時、listと同じように"in"で比較したいなあ(でもできないなあ)とか思ってたんですが、これ、.isin()できるんですね。って話を備忘録にします。

過去記事で「あんまり細かいtipsは記事化してもキリがないなあとは思っているので、コーディングの諸々に関するネタはあんまり書かないつもり云々」とか言っといてアレですが、そこはまあ、はい。

listをinで比較するやつ

listの場合、ある要素がリストに含まれているかどうかは"in"で確認することができます。"not in"で含まれていないことも確認できます。

holiday = ["Sat","Sun"]

print("is holiday")
print(" Mon : ", "Mon" in holiday)
print(" Sat : ", "Sat" in holiday)

print("\nis not holiday")
print(" Mon : ", "Mon" not in holiday)
print(" Sat : ", "Sat" not in holiday)
is holiday
 Mon :  False
 Sat :  True

is not holiday
 Mon :  True
 Sat :  False


pandasでも同じことをやってみる

で、pandasでも同じことができないか考えてみます。ある列を基準に、照合用のリストに要素が含まれていればTrue,そうでなければFalseを返してほしい、という感じです。

以下のようなテーブルを例にします。

import pandas as pd
import numpy as np

df = pd.DataFrame([["Mon","Tue","Mon","Fri","Sat","Sun","Tue","Fri","Mon"],
                   [120,150,200,90,140,180,150,150,120]]).T  
df.columns = ["Day","Sales"]
df
Day Sales
0 Mon 120
1 Tue 150
2 Mon 200
3 Fri 90
4 Sat 140
5 Sun 180
6 Tue 150
7 Fri 150
8 Mon 120


まず大前提として、なんとなく適当に書いてみた以下のコードは動きません。

holiday = ["Sat","Sun"]
df["Day"] in holiday
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-22-0b9535e475c1> in <module>()
----> 1 df["Day"] in holiday

/usr/local/lib/python3.6/dist-packages/pandas/core/generic.py in __nonzero__(self)
   1325     def __nonzero__(self):
   1326         raise ValueError(
-> 1327             f"The truth value of a {type(self).__name__} is ambiguous. "
   1328             "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
   1329         )

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().


正しくは、こう。pandasのisin()メソッドを使います。

holiday = ["Sat","Sun"]
df["Day"].isin(holiday)
0    False
1    False
2    False
3    False
4     True
5     True
6    False
7    False
8    False
Name: Day, dtype: bool


「含まない」場合は、結果の否定を取れば良いです。

holiday = ["Sat","Sun"]
~df["Day"].isin(holiday)
0     True
1     True
2     True
3     True
4    False
5    False
6     True
7     True
8     True
Name: Day, dtype: bool


ちなみにこれを調べた目的は、以下のように変数の水準を新たな別の変数にまとめる処理をしたかったからです。

holiday = ["Sat","Sun"]
df["is_holiday"] = np.where(df["Day"].isin(holiday), True, False)
df
Day Sales is_holiday
0 Mon 120 FALSE
1 Tue 150 FALSE
2 Mon 200 FALSE
3 Fri 90 FALSE
4 Sat 140 TRUE
5 Sun 180 TRUE
6 Tue 150 FALSE
7 Fri 150 FALSE
8 Mon 120 FALSE


おわりに

大したことではない話ですが、「あ、こんなんできるんだ」と思ったので備忘録として。Pythonは誰に習ったわけでもなく我流でなんとなく書いているので、基礎知識がすっぽり抜け落ちている感否めません。