PandasのDataFrameに対してiterrows()メソッドで一つずつ要素を呼び出して,ラベルが存在するかどうかを確かめようとしてエラーに引っかかった話
題名を読んで,わかっている人からすると「何を当たり前のことを書いているんだ」と言われてしまいそうだが,自分がこれで結構引っかかったので一応メモ.
先ず,pandas の DataFrame 配列において
あるラベル名のカラムが存在するのかどうかを確かめたいという時がある.
そんな時には,DataFrame配列の有しているcolumnsという変数を参照することによってその確認を行うことができる.
まず,次の DataFrame配列を用意する.
import pandas as pd test = [ ["Taro", "Tokyo"], ["Jiro", "Osaka"], ["Sinya", "Aichi"], ["Haruki", "Hokkaido"] ] index = ["user", "address"] # DataFrame testpd = pd.DataFrame(test, columns = index) testpd
そして,columnsという変数を参照して,特定のラベル名のカラムが存在するかどうかを確かめることができる.
if "address" in testpd.columns: print(True) else: print(False)
出力結果
True
また,DataFrame配列の中身を一つ一つ取り出したくなる時がある.
そんな時には,DataFrame配列の有するメソッドであるiterrows()を用いることによって実現することができる.
ここからが本題であるが,iterrows()を用いて一つ一つ取り出したアイテムに対して,columnsという変数を参照して,特定のラベル名のカラムが存在するかどうかを確かめようとすると,
for index, item in testpd.iterrows(): # index は 'int' type # item は 'pandas.Series' type print("************************************") print(item) # 'pandas.Series' type に対して,DataFrame型の時と同様に ".columns" を呼び出してみる if "address" in item.columns: print(True) else: print(False)
出力結果
True ************************************ user Taro address Tokyo Name: 0, dtype: object --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-27-555c8ebbccf2> in <module>() 8 # 'pandas.Series' type に対して,DataFrame型の時と同様に ".columns" を呼び出してみる 9 try: ---> 10 if "address" in item.columns: 11 print(True) 12 else: ~\Anaconda3\lib\site-packages\pandas\core\generic.py in __getattr__(self, name) 4366 if (name in self._internal_names_set or name in self._metadata or 4367 name in self._accessors): -> 4368 return object.__getattribute__(self, name) 4369 else: 4370 if self._info_axis._can_hold_identifiers_and_holds_name(name): AttributeError: 'Series' object has no attribute 'columns'
このようにAttributeErrorを食らってしまう.
というのも,公式リファレンスを参照したところ
pandas.DataFrame.iterrows — pandas 0.24.1 documentation
iterrows()メソッドによって渡される値は'DataFrame'オブジェクトではなく,'Series'オブジェクトとして渡されるためである.
Seriesオブジェクトは,columnの無いDataFrameオブジェクト・一次元のDataFrameオブジェクトのようなものであるため,columnsを参照することができないのである.
その代わりに,Seriesオブジェクトはその行(index)のラベルを.keys()メソッドによって参照することができるのである.
for index, item in testpd.iterrows(): # index は 'int' type # item は 'pandas.Series' type print("************************************") print(item) # 'pandas.Series' type に対して メソッド ".keys()" を呼び出してみる if "address" in item.keys(): print(True) else: print(False)
出力結果
************************************ user Taro address Tokyo Name: 0, dtype: object True ************************************ user Jiro address Osaka Name: 1, dtype: object True ************************************ user Sinya address Aichi Name: 2, dtype: object True ************************************ user Haruki address Hokkaido Name: 3, dtype: object True
このようにして,indexを参照することができた.