データ処理の世界では、データの持ち方に縦持ちと横持ちという考え方がある。 縦持ちでは、レコードに種類といったカラムを持たせてデータを追加していく。 それに対し横持ちでは種類ごとにカラムを用意した上でデータを追加する形を取る。 一般的にはデータの持ち方としては縦持ちのものが多いと思う。 今回は pandas で縦持ちのデータを横持ちに直す方法について書く。
使った環境は次の通り。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.13.4 BuildVersion: 17E202 $ python -V Python 3.6.5
下準備
まずは pandas をインストールしておく。
$ pip install pandas
続いて Python のインタプリタを起動する。
$ python
あとは縦持ちの形式になったサンプルの DataFrame オブジェクトを用意する。 今回は、時系列データで商品が売れた数っぽいものを用意した。
>>> import pandas as pd >>> data = [ ... ('2018-05-30 20:00:00', 'Onigiri', 1), ... ('2018-05-30 20:00:00', 'Pan', 2), ... ('2018-05-30 20:00:00', 'Pasta', 1), ... ('2018-05-30 20:00:10', 'Onigiri', 3), ... ('2018-05-30 20:00:20', 'Pan', 2), ... ('2018-05-30 20:00:30', 'Pasta', 1), ... ('2018-05-30 20:01:00', 'Onigiri', 2), ... ('2018-05-30 20:01:00', 'Pan', 2), ... ('2018-05-30 20:01:00', 'Pasta', 2), ... ] >>> columns = ['datetime', 'code', 'amount'] >>> df = pd.DataFrame(data, columns=columns) >>> df = df.assign(datetime = pd.to_datetime(df.datetime, format='%Y-%m-%d %H:%M:%S'))
出来上がる DataFrame はこんな感じ。
>>> df datetime code amount 0 2018-05-30 20:00:00 Onigiri 1 1 2018-05-30 20:00:00 Pan 2 2 2018-05-30 20:00:00 Pasta 1 3 2018-05-30 20:00:10 Onigiri 3 4 2018-05-30 20:00:20 Pan 2 5 2018-05-30 20:00:30 Pasta 1 6 2018-05-30 20:01:00 Onigiri 2 7 2018-05-30 20:01:00 Pan 2 8 2018-05-30 20:01:00 Pasta 2 >>> df.dtypes datetime datetime64[ns] code object amount int64 dtype: object
横持ちにする
それでは上記を横持ちに直してみる。
pandas でデータを横持ちにするときは DataFrame#pivot_table()
を使う。
インデックスには時刻 (datetime) を、集計対象は売れた数 (amount)、カラムの種類は商品 (code) でテーブルを組んでみよう。
集計用の関数には加算 (sum) を指定している。
fill_value
オプションを指定しておくと、値が存在しないときにそれで埋めてくれる。
>>> df.pivot_table(values=['amount'], index=['datetime'], columns=['code'], aggfunc='sum', fill_value=0) amount code Onigiri Pan Pasta datetime 2018-05-30 20:00:00 1 2 1 2018-05-30 20:00:10 3 0 0 2018-05-30 20:00:20 0 2 0 2018-05-30 20:00:30 0 0 1 2018-05-30 20:01:00 2 2 2
いいかんじ。
それぞれのオプションを変えるとテーブルの形を変えられる。 例えばインデックスを指定しない場合は上記から時系列情報が抜ける。
>>> df.pivot_table(values=['amount'], columns=['code'], aggfunc='sum') code Onigiri Pan Pasta amount 6 6 4
インデックスを商品にすれば縦横が入れ替わる。
>>> df.pivot_table(values=['amount'], index=['code'], aggfunc='sum') amount code Onigiri 6 Pan 6 Pasta 4
まあ、とはいえ上2つのような集計なら DataFrame#groupby()
でも十分かな。
>>> df.groupby('code').sum() amount code Onigiri 6 Pan 6 Pasta 4
めでたしめでたし。
Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理
- 作者: Wes McKinney,小林儀匡,鈴木宏尚,瀬戸山雅人,滝口開資,野上大介
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/12/26
- メディア: 大型本
- この商品を含むブログ (19件) を見る
前処理大全[データ分析のためのSQL/R/Python実践テクニック]
- 作者: 本橋智光
- 出版社/メーカー: 技術評論社
- 発売日: 2018/04/13
- メディア: 大型本
- この商品を含むブログ (1件) を見る
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログ (1件) を見る