Pandas の使いかた

およそ半年ぶりの更新ですが,何事もなかったかのように平然とエントリをし始めましたが...
(つくばチャレンジにも参加しました.結果は残念でしたが...また取り組みをアップします.)

最近会社で機械学習の勉強をしていて,その際に Pandas というライブラリを使う必要があったので,概要と使い方を備忘録としてまとめておきます.
勉強に使ったのは下記の本です.一年半くらい前に買って,積読状態になっていたので,活用できる機会ができてよかった...

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理


  • pandas のデータ構造

 大まかにいうと,Series と DataFrame という二種類のデータ構造がある.シリーズというのは,一次元の配列らしいが,Numpyの配列と異なるところは,インデックスというデータラベルの配列がつくところ.まず,IPython を使って Series で遊んでみます.


ライブラリのインポート.

from pandas import Series, DataFrame
import pandas as pd
  • シリーズオブジェクトの作成
In [131]: series = Series([1, 10, 100, 1000])

In [132]: series
Out[132]: 
0       1
1      10
2     100
3    1000
dtype: int64

上の出力を見てみると,Numpyの配列とは違って,勝手にインデックスが付与されていることがわかります.
また,このインデックスに関しては,自分で好きなものを付与することもできます.

  • インデックスラベルを指定したシリーズオブジェクトの作成
In [134]: series_w_index_specified = Series([1, 10, 100, 1000], index=['JPN', 'USA', 'GER', 'GBR'])

In [135]: series_w_index_specified
Out[135]: 
JPN       1
USA      10
GER     100
GBR    1000
dtype: int64
  • データフレームオブジェクトの作成

 シリーズが一次元の配列であるのに対し,こちらは二次元の配列というかテーブル風のデータ構造.

In [151]: data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 
     ...: 'year' : ['2000', '2001', '2002', '2001', '2002'], 
     ...: 'pop' :['1.5', '1.7', '3.6', '2.4', '2.9']}

In [152]: frame = DataFrame(data)

In [153]: frame

In [154]: Out[153]: 
   pop   state  year
0  1.5    Ohio  2000
1  1.7    Ohio  2001
2  3.6    Ohio  2002
3  2.4  Nevada  2001
4  2.9  Nevada  2002

 これが使いたかったんです.以前 SQL を使ってデータベースの処理をしていたことがあったんですが,テーブルの結合とかと等価の処理を自分で作るのは時間もかかるしめんどくさいし..ということで,pandas を使ってデータセットをマージする方法をメモ.

pandas.merge : データフレームに含まれる行を一つ以上のキーでマージできる.
pandas.concat : 複数の列のオブジェクトを貼り合わせたり,積み上げたりすることが可能.

    • pandas.merge を使ったデータフレームのマージ
In [9]: df1 = DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
   ...: 'data1': range(7)})

In [10]: df2 = DataFrame({'key': ['a', 'b', 'd'],
    ...: 'data2': range(3)})

In [11]: df1
Out[11]: 
   data1 key
0      0   b
1      1   b
2      2   a
3      3   c
4      4   a
5      5   a
6      6   b

In [12]: df2
Out[12]: 
   data2 key
0      0   a
1      1   b
2      2   d

上で作成したデータを,pandas.merge を使ってマージします.
超簡単ですね.ありがたやありがたや.

In [15]: pd.merge(df1, df2, on = 'key')
Out[15]: 
   data1 key  data2
0      0   b      1
1      1   b      1
2      6   b      1
3      2   a      0
4      4   a      0
5      5   a      0


結合する列の名前が左右のテーブルで異なるときもあると思いますが,こちらに関しても下記のようにすれば結合できるみたいです.
両方にキーが存在する行のみがマージされた結果に残されている様子が見て取れます.この結合を内部結合といい,結果に表れるキーは両者の共通集合になります.

In [22]: df3 = DataFrame({'lkey':['b', 'b', 'a', 'c', 'a', 'a', 'b'],
    ...: 'data1': range(7)})

In [23]: df4 = DataFrame({'rkey':['a', 'b', 'd'],
    ...: 'data2': range(3)})

In [24]: pd.merge(df3, df4, left_on='lkey', right_on='rkey')
Out[24]: 
   data1 lkey  data2 rkey
0      0    b      1    b
1      1    b      1    b
2      6    b      1    b
3      2    a      0    a
4      4    a      0    a
5      5    a      0    a

一方で,どちらか片方に存在するキーも消したくない場合もあると思います.この場合には,外部結合を実施すれば結合できます.
ただし,ペアとなるキーが相手方に存在しない場合はそのデータはNaNとなります.下記の実行結果を見てもわかる通り,結合ペアのキーのない箇所はデータが NaN になっています.

In [25]: pd.merge(df3, df4, left_on='lkey', right_on='rkey', how='outer')
Out[25]: 
   data1 lkey  data2 rkey
0    0.0    b    1.0    b
1    1.0    b    1.0    b
2    6.0    b    1.0    b
3    2.0    a    0.0    a
4    4.0    a    0.0    a
5    5.0    a    0.0    a
6    3.0    c    NaN  NaN
7    NaN  NaN    2.0    d