Pandasのデータフレーム内の検索はマスクが便利

※追記 2021
いつのバージョンからかは知らないが、今は.ixしないで↓でいける

```
df[df["B"].isnull()]
```



----

Pythonで色々なデータを扱う時に使うPandasですが、特定の数値を検索したりする時に今まで普通に`for`や`df.iterrows()`などで一列ずつ処理してました。
でもデータが大きくなると遅いんですよね。

何か良い方法がないか調べてみると、どうやら`df.ix[]`をマスク(フィルター?)として使うと良いみたいです。


例えばこんなデータフレームがあったとします。

```py
print df

                           A        B         C         D         E
TIME                                                                   
2001-01-08 06:00:00  -0.5925    -1.11  0.055023 -0.074103  0.129126    
2001-01-08 06:05:00  -0.4213      NaN       NaN       NaN       NaN
2001-01-08 06:10:00  -0.3613    -2.19       NaN       NaN       NaN    
2001-01-08 06:15:00  -0.3613      NaN       NaN       NaN  0.224574   
2001-01-08 06:20:00  -0.3613      NaN  0.129036 -0.000281  1.094003   
2001-01-08 06:25:00  -0.8243    -0.65  0.137242 -0.022502  2.145931   
```

行BでNaNになっている列を知りたい

```py
print df.ix[df["B"].isnull()]

                           A        B         C         D         E
TIME                                                                   
2001-01-08 06:05:00  -0.4213      NaN       NaN       NaN       NaN
2001-01-08 06:15:00  -0.3613      NaN       NaN       NaN  0.224574
2001-01-08 06:20:00  -0.3613      NaN  0.129036 -0.000281  1.094003      
```

行EでNaNになってない列を知りたい

```py
print df.ix[df["E"].isnull()==False]

                           A        B         C         D         E
TIME                                                                   
2001-01-08 06:00:00  -0.5925    -1.11  0.055023 -0.074103  0.129126    
2001-01-08 06:15:00  -0.3613      NaN       NaN       NaN  0.224574
2001-01-08 06:20:00  -0.3613      NaN  0.129036 -0.000281  1.094003
2001-01-08 06:25:00  -0.8243    -0.65  0.137242 -0.022502  2.145931         
```

どの行がNaNになっていても検索ヒット

```py
print df.ix[df.isnull().values.any()]

                           A        B         C         D         E
TIME                                                                   
2001-01-08 06:05:00  -0.4213      NaN       NaN       NaN       NaN
2001-01-08 06:10:00  -0.3613    -2.19       NaN       NaN       NaN    
2001-01-08 06:15:00  -0.3613      NaN       NaN       NaN  0.224574   
2001-01-08 06:20:00  -0.3613      NaN  0.129036 -0.000281  1.094003   
```


最初の3つの列で、行CがNaNになっている列だけ欲しい

```py
print df.ix[df["C"].isnull(), :3]

                           A        B         C         D         E
TIME                                                                   
2001-01-08 06:05:00  -0.4213      NaN       NaN       NaN       NaN
2001-01-08 06:10:00  -0.3613    -2.19       NaN       NaN       NaN 
```



行DでNaNになっている列の行AとBが欲しい

```py
print df.ix[df["D"].isnull(), ["A", "B"]]

                           A        B
TIME                                                                   
2001-01-08 06:05:00  -0.4213      NaN
2001-01-08 06:10:00  -0.3613    -2.19
2001-01-08 06:15:00  -0.3613      Nan
```


行DでNaNになっている列の行Aの数値を操作(1引いてみる)

```py
df.ix[df["D"].isnull(), "A"] -= 1 
print df["A"]

                           A
TIME                          
2001-01-08 06:00:00  -0.5925                 
2001-01-08 06:05:00  -1.4213
2001-01-08 06:10:00  -1.3613
2001-01-08 06:15:00  -1.3613
2001-01-08 06:20:00  -0.3613 
2001-01-08 06:25:00  -0.8243  
```

上記の状態で条件検索

```py
print df["A"]

                           A
TIME                          
2001-01-08 06:00:00  -0.5925                 
2001-01-08 06:05:00  -1.4213
2001-01-08 06:10:00  -1.3613
2001-01-08 06:15:00  -1.3613
2001-01-08 06:20:00  -0.3613 
2001-01-08 06:25:00  -0.8243  


print df.ix[df["A"]<= -1] 

                           A        B         C         D         E
TIME                      
2001-01-08 06:05:00  -1.4213      NaN       NaN       NaN       NaN
2001-01-08 06:10:00  -1.3613    -2.19       NaN       NaN       NaN    
2001-01-08 06:15:00  -1.3613      NaN       NaN       NaN  0.224574   
```


この例では小さいですが、大きなデータフレームでも全然早いです。

---

追記
各列の数値を複雑な条件式で操作をしたい場合などは`df.apply(function, axis=1)`がベストっぽい。