Python で解析 15

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

1. データの準備

今回は、fillna を使ってみる。いつも綺麗なデータなら良いのだが、欠損しているデータをどうにかしなきゃならないシチュエーションだ。

In [1]: import pandas as pd

In [2]: df1 = pd.DataFrame({
   ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'],
   ...: u'性別': [u'男', u'男', u'女', u'女'] ,
   ...: u'身長': [181, 173, 159, 164],
   ...: u'体重': [79, 71, 51, 52]
   ...: }, index=['3B005', '3B003', '3B002', '3B001'])

In [3]: df2 = pd.DataFrame({
   ...:  u'誕生日': ['1981/01/01', '1982/02/02', '1983/03/03', '1984/04/04']
   ...: }, index=['3B004','3B005','3B003', '3B002'])

In [4]: df3 = pd.DataFrame({
   ...:  u'好きなもの': [u'りんご', u'ばなな', u'いちご', u'メロン'],
   ...: }, index=['3B004','3B005','3B003', '3B001'])

In [5]: df = df1.join([df2, df3])

In [6]: df
Out[6]:
       体重  名前 性別   身長         誕生日 好きなもの
3B005  79  山田  男  181  1982/02/02   ばなな
3B003  71  鈴木  男  173  1983/03/03   いちご
3B002  51  佐藤  女  159  1984/04/04   NaN
3B001  52  木村  女  164         NaN   メロン

今回は nan を作るために、join している。

2. nan の数も合わせて算出したい

例えば、データの個数を数えてみると nan の数が分からない。

In [7]: df[u'好きなもの'].value_counts()
Out[7]:
ばなな    1
メロン    1
いちご    1
dtype: int64

好きなものがわからない数も把握したので、nan のところに '不明' と入れてみることにする。

In [8]: df.fillna(u'不明')
Out[8]:
       体重  名前 性別   身長         誕生日 好きなもの
3B005  79  山田  男  181  1982/02/02   ばなな
3B003  71  鈴木  男  173  1983/03/03   いちご
3B002  51  佐藤  女  159  1984/04/04    不明
3B001  52  木村  女  164          不明   メロン

誕生日の欄も不明が入った。これでもかまわないのだが、カラムを限定することもできる。

In [9]: df.fillna({u'好きなもの': u'不明'})
Out[9]:
       体重  名前 性別   身長         誕生日 好きなもの
3B005  79  山田  男  181  1982/02/02   ばなな
3B003  71  鈴木  男  173  1983/03/03   いちご
3B002  51  佐藤  女  159  1984/04/04    不明
3B001  52  木村  女  164         NaN   メロン

今度は、好きなもののカラムだけが変更された。この状態で、もう一度、データの個数を数えてみる。

In [10]: df[u'好きなもの'].value_counts()
Out[10]:
ばなな    1
メロン    1
いちご    1
dtype: int64

ん? 最初と同じ結果になってしまった。

3. 元の DataFrame に反映したい

実は、次のようにすれば不明分もカウントされる。

In [11]: df[u'好きなもの'].fillna(u'不明').value_counts()
Out[11]:
ばなな    1
不明     1
メロン    1
いちご    1
dtype: int64

fillna が新しいオブジェクトを返すので、元の DataFrame に '不明' が反映されなかったのが、先ほどの失敗の原因だ。

次のようにすると、元の DataFrame に反映される。

In [12]: df[u'好きなもの'] = df[u'好きなもの'].fillna(u'不明')

In [13]: df
Out[13]:
       体重  名前 性別   身長         誕生日 好きなもの
3B005  79  山田  男  181  1982/02/02   ばなな
3B003  71  鈴木  男  173  1983/03/03   いちご
3B002  51  佐藤  女  159  1984/04/04    不明
3B001  52  木村  女  164         NaN   メロン

あるいは df を入れ替えてしまってもいい。

In [14]: df = df.fillna({u'好きなもの': u'不明'})

In [15]: df
Out[15]:
       体重  名前 性別   身長         誕生日 好きなもの
3B005  79  山田  男  181  1982/02/02   ばなな
3B003  71  鈴木  男  173  1983/03/03   いちご
3B002  51  佐藤  女  159  1984/04/04    不明
3B001  52  木村  女  164         NaN   メロン

今度は、不明分もカウントされるハズだ。

In [16]: df[u'好きなもの'].value_counts()
Out[16]:
ばなな    1
不明     1
メロン    1
いちご    1
dtype: int64

今回はこんなところで。