1. ホーム
  2. パイソン

[解決済み】pandas.DataFrameから複雑な条件での選択

2022-03-29 19:48:48

質問

例えば、簡単なDFがあります。

import pandas as pd
from random import randint

df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)],
                   'B': [randint(1, 9)*10 for x in xrange(10)],
                   'C': [randint(1, 9)*100 for x in xrange(10)]})

Pandasのメソッドとイディオムを使って、'A'から'B'の対応する値が50より大きく、'C'の値が900に等しくない値を選択することは可能ですか?

どのように解決するのですか?

もちろんです!(笑 セットアップです。

>>> import pandas as pd
>>> from random import randint
>>> df = pd.DataFrame({'A': [randint(1, 9) for x in range(10)],
                   'B': [randint(1, 9)*10 for x in range(10)],
                   'C': [randint(1, 9)*100 for x in range(10)]})
>>> df
   A   B    C
0  9  40  300
1  9  70  700
2  5  70  900
3  8  80  900
4  7  50  200
5  9  30  900
6  2  80  700
7  2  80  400
8  5  80  300
9  7  70  800

列の操作を適用して、ブーリアン Series オブジェクトを取得することができる。

>>> df["B"] > 50
0    False
1     True
2     True
3     True
4    False
5    False
6     True
7     True
8     True
9     True
Name: B
>>> (df["B"] > 50) & (df["C"] == 900)
0    False
1    False
2     True
3     True
4    False
5    False
6    False
7    False
8    False
9    False

[新スタイルへの移行に伴うアップデート .loc ]:

そして、これらを使って、オブジェクトにインデックスを付けることができます。 読み取りアクセスの場合は、インデックスを連鎖させることができます。

>>> df["A"][(df["B"] > 50) & (df["C"] == 900)]
2    5
3    8
Name: A, dtype: int64

しかし、ビューとコピーの違いは、書き込みアクセスのためにこれを行うので、問題になることがあります。 この場合 .loc の代わりに

>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"]
2    5
3    8
Name: A, dtype: int64
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"].values
array([5, 8], dtype=int64)
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"] *= 1000
>>> df
      A   B    C
0     9  40  300
1     9  70  700
2  5000  70  900
3  8000  80  900
4     7  50  200
5     9  30  900
6     2  80  700
7     2  80  400
8     5  80  300
9     7  70  800

なお、私は誤って == 900 でなく != 900 または ~(df["C"] == 900) しかし、私はそれを修正するのが億劫なのです。読者のための練習問題です :^)