Pandas の DataFrame には苦手意識がある。あまりにインターフェイスが複雑すぎてわけがわからない。特に一番複雑なのは [](__getitem__)
。ドキュメントがまともにない。
やはり同じようなことを考えていた人が stack overflow にいた。
Pandas DataFrame: complete spec for __getitem__()?
結局、ソースコードを読め、ということらしい。普通に Python で書いてあるので読めることは読める。frame.py
というファイルに書いてある。私が一番気になるのは、 __getitem__
にリストを与えたときの挙動だ。__getitem__
から呼び出されている次のメソッドに答えがあった(pandas のバージョンは 0.22.0)。
def _getitem_array(self, key):
# also raises Exception if object array with NA values
if com.is_bool_indexer(key):
# warning here just in case -- previously __setitem__ was
# reindexing but __getitem__ was not; it seems more reasonable to
# go with the __setitem__ behavior since that is more consistent
# with all other indexing behavior
if isinstance(key, Series) and not key.index.equals(self.index):
warnings.warn("Boolean Series key will be reindexed to match "
"DataFrame index.", UserWarning, stacklevel=3)
elif len(key) != len(self.index):
raise ValueError('Item wrong length %d instead of %d.' %
(len(key), len(self.index)))
# check_bool_indexer will throw exception if Series key cannot
# be reindexed to match DataFrame rows
key = check_bool_indexer(self.index, key)
indexer = key.nonzero()[0]
return self._take(indexer, axis=0, convert=False)
else:
indexer = self.loc._convert_to_indexer(key, axis=1)
return self._take(indexer, axis=1, convert=True)
com.is_bool_indexer(key)
で key が bool(真偽値)かどうかチェックしているのが味噌。
要するに、
- bool なら、行のセレクタ
- bool 以外なら、列のセレクタ
として動作しているということだ。
だから、
df[df.x == 1]
なら、「カラムx が 1 である行を抜き出して DataFrame として返す」し、
df[['x']]
なら、「カラムxだけを抜き出して DataFrame として返す」という動作になる。
同じようなことは、loc
を使ってもできるので、動作が曖昧な __getitem__
はあまり使わないほうがいいのかもしれない。ただ、簡潔に書けるのは魅力的なので、用量を守って使用すればいいのかな。