Python で解析 13

“Advent Calendar 2013 - Python で解析!” の十三日目。DataFrame - 8

1. データの準備

今回は cut を取り上げる。例えば、身長 10cm 刻みでの平均身長、平均体重を算出する…などで使うことができる。たぶん、 SQL にはない機能で、もし SQL で実現するなら case 式を使うだろう。

では、データの準備を。

In [1]: import pandas as pd

In [2]: df = pd.DataFrame({
   ...: 'height': [162, 178, 167, 171, 170],
   ...: 'weight': [51, 80, 55, 68, 71]
   ...: })

In [3]: df
Out[3]:
   height  weight
0     162      51
1     178      80
2     167      55
3     171      68
4     170      71

何はともあれ cut を使ってみると、こうなる。

In [4]: df.groupby(pd.cut(df.height, [160, 170, 180])).mean()
Out[4]:
                height  weight
height
(160, 170]  166.333333      59
(170, 180]  174.500000      74

何ができるか、なんとなく分かっただろうか?

2. cut とは

試しに cut のところだけを実行してみる。

In [5]: pd.cut(df.height, [160, 170, 180])
Out[5]:
Categorical: height
[(160, 170], (170, 180], (160, 170], (170, 180], (160, 170]]
Levels (2): Index(['(160, 170]', '(170, 180]'], dtype=object)

ちょっと分かりにくいかもしれないが、こんな風に置き換わっている。

162 -> (160, 170] # 160 以上、170 未満
178 -> (170, 180] # 170 以上、180 未満
167 -> (160, 170] # 160 以上、170 未満
171 -> (170, 180] # 170 以上、180 未満
170 -> (170, 180] # 170 以上、180 未満

cut の二番目の引数に境界値を設定するだけで、データを分類してくれるので、とっても便利。ニュースで年代別だったり、所得区分別だったり…の統計値が取り上げられるが、そーゆー時に使える。

なお、デフォルトでは (以上, 未満] だが、[より大きい、以下) という指定もできる。

In [6]: pd.cut(df.height, [160, 170, 180], right=False)
Out[6]:
Categorical: height
[[160, 170), [170, 180), [160, 170), [170, 180), [170, 180)]
Levels (2): Index(['[160, 170)', '[170, 180)'], dtype=object)

3. qcut も

cut では、境界値を設定して分類したが、 qcut は分割数に応じて、実際のデータを分割する。

In [7]: pd.qcut(df.height, 2)
Out[7]:
Categorical: height
[[162, 170], (170, 178], [162, 170], (170, 178], [162, 170]]
Levels (2): Index(['[162, 170]', '(170, 178]'], dtype=object)

二つに分割されたことが Levels の方を見ると分かる。

In [8]: pd.qcut(df.height, 4)
Out[8]:
Categorical: height
[[162, 167], (171, 178], [162, 167], (170, 171], (167, 170]]
Levels (4): Index(['[162, 167]', '(167, 170]', '(170, 171]',
                   '(171, 178]'], dtype=object)

四つに分割された。

「二十代の人の…」という時は cut で、「上位 25% の人の…」という時は qcut を使うという感じで、使い分ける。

今回はこんなところで。