質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

2回答

5497閲覧

pandasの条件付のカラムの抽出の方法について

fu_3823

総合スコア81

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2021/02/14 11:31

編集2021/02/14 11:33

以下のようなデータフレームで、cat_1とcat_2のdtypeが'category'とします。
そのとき、カラム名である'cat_1'と'cat_2'を抽出したいのですが、そのコードについて質問があります。

cat_1cat_2num_1
113.32
231.45
212.22

以下のように書けば、意図した通りに取得できます。

Python

1categories = train_X.columns[train_X.dtypes == 'category'] 2# Index(['cat1', 'cat2'], dtype='object')

しかし、感覚的には、次ような書き方が正しいように思うのですが、これはエラーになります。
何が間違っているのでしょう。

Python

1categories = train_X[train_X.dtypes == 'category'].columns 2# IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).

先に、条件に該当する列を抽出し、その列についてカラム名を取り出すと考えれば、後者のような書式になるように思うのですが、考え違いをしているのでしょうか。エラーの説明もUnalignable boolean Seriesがどういうもの指しているのかがわからず、行き詰まってしまいました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

pandasのdf[xxx]は、多くの場合はcolumnに対する選択になるのですが、xxxがbooleanの配列の場合は、rowに対する選択として機能します。
リファレンス(https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#boolean-indexingあたり)に、書いてあります。
(そのほかにも、たとえばxxxがスライスの場合もrowに対する選択です。)

なので、行数と train_X.dtypes == 'category' の要素数があっていないことになり、そのエラーになっています。
今回は配列ではなくSeriesを渡しているので、DataFrame(train_X)のインデックスと、Series(train_X.dtypes == 'category')のインデックスの一致もチェックされます。
両者のインデックスがあっていないというエラーです。

対策としては、

python

1categories = train_X.loc[:, train_X.dtypes == 'category'].columns

.locを使って、columnの選択であることを明示すればよいと思います。

投稿2021/02/14 13:18

編集2021/02/14 23:27
bsdfan

総合スコア4794

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fu_3823

2021/03/07 17:22

コメント遅くなりすみません。大変参考なりました。ありがとうございました。
guest

0

ベストアンサー

train_X[train_X.dtypes == 'category'].columns がエラーになるのは、
「条件に該当する列を抽出し」を train_X[train_X.dtypes == 'category'] ではできないからです。
fu_3823さんの期待する「条件に該当する列を抽出し」は以下だと思われます。

python

1 cat_1 cat_2 20 1 1 31 2 3 42 2 1

では、train_X[train_X.dtypes == 'category']を調べてみましょう。

python

1>>> print(train_X) 2 cat_1 cat_2 num_1 30 1 1 3.32 41 2 3 1.45 52 2 1 2.22 6>>> print(train_X.dtypes == 'category') 7cat_1 True 8cat_2 True 9num_1 False 10dtype: bool 11>>> print(train_X[train_X.dtypes == 'category']) 12>> print(train_X) 13 cat_1 cat_2 num_1 140 1 1 3.32 151 2 3 1.45 162 2 1 2.22 17>>> print(train_X.dtypes == 'category') 18cat_1 True 19cat_2 True 20num_1 False 21dtype: bool 22>>> print(train_X[train_X.dtypes == 'category']) 23<stdin>:1: UserWarning: Boolean Series key will be reindexed to match DataFrame index. 24Traceback (most recent call last): 25 File "<stdin>", line 1, in <module> 26 File "C:\Users\shinp\anaconda3\lib\site-packages\pandas\core\frame.py", line 2791, in __getitem__ 27 return self._getitem_bool_array(key) 28 File "C:\Users\shinp\anaconda3\lib\site-packages\pandas\core\frame.py", line 2843, in _getitem_bool_array 29 key = check_bool_indexer(self.index, key) 30 File "C:\Users\shinp\anaconda3\lib\site-packages\pandas\core\indexing.py", line 2317, in check_bool_indexer 31 raise IndexingError( 32pandas.core.indexing.IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).

なぜできないのかを調べてみましょう。

python

1>>> print(type(train_X.dtypes == 'category')) 2<class 'pandas.core.series.Series'> 3>>> print((train_X.dtypes == 'category').index) 4Index(['cat_1', 'cat_2', 'num_1'], dtype='object') 5>>> print((train_X.dtypes == 'category').values) 6[ True True False]

これでわかるように、train_X.dtypes == 'category'はpandasのSeriesオブジェクトであり、train_X.dtypes == 'category'のindexはIndex(['cat_1', 'cat_2', 'num_1'], dtype='object')で値は、[ True True False]です。

A[train_X.dtypes == 'category']が値を持つためにはAがindexオブジェクトであるか、AがDataFrameオブジェクトかSeriesオブジェクトで、そのindexがIndex(['cat_1', 'cat_2', 'num_1']でなければなりません。(これはpandasの仕様です)
このために、train_X[train_X.dtypes == 'category']はエラーになります。

なぜ、train_X.columns[train_X.dtypes == 'category']の方は正しく動くかというと、train_X.columnsは以下のindexオブジェクトだからです。

python

1>>> print(train_X.columns) 2Index(['cat_1', 'cat_2', 'num_1'], dtype='object')

どうしても、「条件に該当する列を抽出」をやりたいなら、以下の方法でつくることは可能です。

python

1>>> train_X.T[train_X.dtypes == 'category'].T 2 cat_1 cat_2 30 1 1 41 2 3 52 2 1

投稿2021/02/14 13:04

ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fu_3823

2021/03/07 17:21

詳しい回答ありがとうございました。大変参考になりした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問