<Python, pandas> booleanのリストを使った行列選択

booleanlistか、Seriesを使いデータフレームDataFrameの行列選択する。

データフレームから、Noneの部分を.applymapを使って判定。

In [129]: df
Out[129]: 
    a     b
0   1  None
1   2   NaN
2   3     5
3 NaN     8
4   4     a
5   5     9
6 NaN     8
7   6  None

In [130]: a = df.applymap(lambda x: isinstance(x, type(None)))

In [131]: a
Out[131]: 
       a      b
0  False   True
1  False  False
2  False  False
3  False  False
4  False  False
5  False  False
6  False  False
7  False   True

判定結果をそのまま渡すと、Falseの部分がnp.nanになる。
.dropna()でもすれば、Falseの部分を削れる。

In [132]: df[a]
Out[132]: 
    a     b
0 NaN  None
1 NaN   NaN
2 NaN   NaN
3 NaN   NaN
4 NaN   NaN
5 NaN   NaN
6 NaN   NaN
7 NaN  None

booleanの計算は下記。
ビット演算だから、|でOR、&でAND。

In [133]: a['a'] | a['b']
Out[133]: 
0     True
1    False
2    False
3    False
4    False
5    False
6    False
7     True
dtype: bool

In [134]: a['a'] & a['b']
Out[134]: 
0    False
1    False
2    False
3    False
4    False
5    False
6    False
7    False
dtype: bool

で、できたSerieslistを渡すと、
Trueの行indexが選択できる。

In [135]: s = a['a'] | a['b']

In [136]: df[s]
Out[136]: 
   a     b
0  1  None
7  6  None

In [137]: type(s)
Out[137]: pandas.core.series.Series

In [138]: l = (a['a'] | a['b']).tolist()

In [139]: df[l]
Out[139]: 
   a     b
0  1  None
7  6  None

In [140]: type(l)
Out[140]: list

Columnを選択する場合は、.loc

In [141]: c = [True, False]

In [142]: df.loc[:, c]
Out[142]: 
    a
0   1
1   2
2   3
3 NaN
4   4
5   5
6 NaN
7   6

index:で全選択しておかないと、エラー。

In [143]: df.loc[, c]
  File "<ipython-input-143-cdf1799e5c5f>", line 1
    df.loc[, c]
           ^
SyntaxError: invalid syntax

だけど、列Columnの場合はいいらしい。不思議。

In [144]: df[s]
Out[144]: 
   a     b
0  1  None
7  6  None

In [145]: df.loc[s, :]
Out[145]: 
   a     b
0  1  None
7  6  None

In [146]: df.loc[s, ]
Out[146]: 
   a     b
0  1  None
7  6  None

Stackoverflow

stackoverflow.com

stackoverflow.com

追加。

Noneを選択する方法は、.applymap(lambda x: isinstance(x, type(None)))じゃなくて、 もっと簡単に、.isin([None])でいけた。
.any()と組み合わせれば、ちゃっと行列も絞り込める。

In [162]: df
Out[162]: 
   a   b     c
0  a  ab     x
1  b  bb  None
2  c  bc     z

In [164]: df.isin([None])
Out[164]: 
       a      b  \
0  False  False   
1  False  False   
2  False  False   

       c  
0  False  
1   True  
2  False  

In [165]: df.isin([None]).any()
Out[165]: 
a    False
b    False
c     True
dtype: bool

In [166]: df.isin([None]).any(axis=1)
Out[166]: 
0    False
1     True
2    False
dtype: bool

In [167]: df[df.isin([None])]
Out[167]: 
     a    b     c
0  NaN  NaN   NaN
1  NaN  NaN  None
2  NaN  NaN   NaN

In [168]: df[~df.isin([None])]
Out[168]: 
   a   b    c
0  a  ab    x
1  b  bb  NaN
2  c  bc    z