今回はPandasのピボットテーブルの使い方について学習します。
ピボット の使い方はその場では理解したつもりでも、なかなか使いこなせていない場合も多いと思います。
その原因はピボットの関数の使い方というよりも、そもそもピボットで何をしたいのかをきちんと理解していないためだと思います。
そしてピボットがうまく理解できないのは、そもそも縦持ちのデータ(longフォーマット)と横持ちのデータ(wideフォーマット)の違いや特徴を理解しないでピボットを使おうとするためです。
基本的にはピボットは縦持ちのデータを横持ちに変えるためのものと捉えておくと良いでしょう。
それでは、縦持ちデータと横持ちデータの違いについて説明します。
縦持ちデータと横持ちデータの違い
縦持ちデータについて
縦持ちのデータは、カラムが固定になっている表になっているものです。データベースのテーブルなどでよく使われる方式です。
縦持ちから横持ちに変更するにはピボットを使えばよく、比較的簡単に変更できます。
横持ちデータについて
横持ちは、カラム数が可変で1行に複数のカラムをもたせているテーブルです。特徴として、分析しやすい反面データベースに保存するときには不都合です。また横持ちから縦持ちに変更するのは面倒な処理が必要なことが多いです。
ピボットを活用して横持ちに変更した例
pivot関数
縦持ちデータの項目を横持ちに変えることができます。
ただし、pivot関数を使うときのポイントは、ラベルどうし(index,columnsに指定した値)にダブリがあるとエラーになります。
これは結構起こりがちですから注意してください。
pivot関数の使い方
DataFrame.pivot(index=None, columns=None, values=None)
与えられたインデックス/列の値で編成された、再形成されたDataFrameを返します。列の値に基づいてデータを再形成します(「ピボット」テーブルを作成します)。指定されたインデックス / 列の一意の値を使用して、結果のDataFrameの軸を形成します。この関数はデータの集約をサポートしていません。複数の値を指定すると、列にMultiIndexが発生します。再形成の詳細については、ユーザーガイドを参照してください。
パラメータ
- index:str or object or a list of str, optional
新しいフレームのインデックスを作成するために使用する列。Noneの場合、既存のインデックスを使用します。
バージョン1.1.0で変更:インデックス名のリストも受け入れます。- columns:str or object or a list of str
新しいフレームの列を作成するために使用する列。
バージョン1.1.0で変更:列名のリストも受け入れます。- values:str, object or a list of the previous, optional
新しいフレームの値を入力するために使用する列。指定しない場合、残りのすべての列が使用され、結果には階層的にインデックス付けされた列が含まれます。
バージョン0.23.0で変更:列名のリストも受け入れます。返り値
DataFrame
整形されたDataFrameを返します。ValueErrorが出る対策
インデックス、列が複数の値を持つ組み合わせがあり、集約する必要がある場合は「DataFrame.pivot_table」を使いましょう。
pivot_table関数
pivot_tableはpivotと同様の動きをしますがこちらは集計機能が備わっています。そのため、ラベルどうし(index,columnsに指定した値)にダブリがあってもそれを集計します。デフォルトの関数はsumで、引数で指定することで変更できます。もし、文字列の値の場合はエラーになります。
pivot_table関数のドキュメント
pivot_table関数の使い方
pandas.pivot_table(data, values=None, index=None, columns=None, aggfunc=’mean’, fill_value=None, margins=False, dropna=True, margins_name=’All’, observed=False)
スプレッドシートスタイルのピボットテーブルをDataFrameとして作成します。
ピボットテーブルのレベルは、結果のDataFrameのインデックスと列のMultiIndexオブジェクト(階層インデックス)に格納されます。Parameters
- data:DataFrame
- values:column to aggregate, optional
- index:column, Grouper, array, or list of the previous
配列が渡される場合、配列はデータと同じ長さでなければなりません。リストには他のタイプを含めることができます(リストを除く)。ピボットテーブルのインデックスでグループ化するキー。配列が渡された場合は、列の値と同じ方法で使用されます。- columns:column, Grouper, array, or list of the previous
配列が渡される場合、配列はデータと同じ長さでなければなりません。リストには他のタイプを含めることができます(リストを除く)。ピボットテーブルの列でグループ化するキー。配列が渡された場合は、列の値と同じ方法で使用されます。- aggfunc:function, list of functions, dict, default numpy.mean
関数のリストが渡された場合、結果のピボットテーブルには、関数名(関数オブジェクト自体から推測)がトップレベルである階層列が含まれます。dictが渡された場合、キーは集計する列であり、値は関数または関数のリストです。- fill_value:scalar, default None
欠損値を置き換える値(結果のピボットテーブル、集計後)- margins:bool, default False
すべての行/列を追加します(たとえば、小計/総計の場合)- dropna:bool, default True
エントリがすべてNaNである列を含めないでください。- margins_namestr, default ‘All’
マージンがTrueの場合に合計を含む行/列の名前。- observed:bool, default False
これは、ハタのいずれかがカテゴリカルである場合にのみ適用されます。Trueの場合:カテゴリーハタの観測値のみを表示します。Falseの場合:カテゴリグループのすべての値を表示します。
バージョン0.25.0で変更されました。Returns
DataFrame
Excelスタイルのピボットテーブル
pivot_table関数とpivot関数の実例
次のコードはうどん屋さんのcsvデータをDataFrame形式で読み込んだとします。
CSVファイルはカレントディレクトリに置いているものとします。
udon = pd.read_csv('udon_data.csv') udon
結果
月日 | 麺 | トッピング | その他 | 麺金額 | トッピング金額 | その他金額 | 合計金額 | |
---|---|---|---|---|---|---|---|---|
0 | 8/1 | うどん | イカ天 | NaN | 300 | 150.0 | NaN | 450 |
1 | 8/1 | そば | たまご | いなり | 300 | 50.0 | 100.0 | 450 |
2 | 8/1 | そば | ちくわ天 | おにぎり | 300 | 120.0 | 100.0 | 520 |
3 | 8/1 | うどん | ゴボウ天 | NaN | 300 | 120.0 | NaN | 420 |
4 | 8/1 | うどん | NaN | NaN | 300 | NaN | NaN | 300 |
5 | 8/2 | そば | たまご | いなり | 300 | 50.0 | 100.0 | 450 |
6 | 8/2 | そば | ちくわ天 | おにぎり | 300 | 120.0 | 100.0 | 520 |
7 | 8/2 | うどん | ゴボウ天 | NaN | 300 | 120.0 | NaN | 420 |
8 | 8/2 | うどん | ゴボウ天 | NaN | 300 | 120.0 | NaN | 420 |
9 | 8/2 | うどん | 鳥天 | NaN | 300 | 150.0 | NaN | 450 |
10 | 8/3 | そば | NaN | いなり | 300 | NaN | 100.0 | 400 |
11 | 8/3 | そば | NaN | NaN | 300 | NaN | NaN | 300 |
12 | 8/3 | そば | イカ天 | NaN | 300 | 150.0 | NaN | 450 |
13 | 8/3 | そば | たまご | おにぎり | 300 | 50.0 | 100.0 | 450 |
14 | 8/3 | うどん | ゴボウ天 | NaN | 300 | 120.0 | 100.0 | 520 |
15 | 8/3 | うどん | たまご | NaN | 300 | 50.0 | 100.0 | 450 |
16 | 8/3 | うどん | ゴボウ天 | NaN | 300 | 120.0 | NaN | 420 |
17 | 8/4 | うどん | 鳥天 | NaN | 300 | 150.0 | NaN | 450 |
18 | 8/4 | うどん | NaN | いなり | 300 | NaN | 100.0 | 400 |
19 | 8/4 | うどん | 鳥天 | いなり | 300 | 150.0 | 100.0 | 550 |
20 | 8/4 | そば | NaN | NaN | 300 | NaN | NaN | 300 |
21 | 8/4 | そば | ちくわ天 | おにぎり | 300 | 120.0 | 100.0 | 520 |
22 | 8/5 | うどん | ゴボウ天 | NaN | 300 | 120.0 | NaN | 420 |
23 | 8/5 | うどん | ゴボウ天 | いなり | 300 | 120.0 | 100.0 | 520 |
24 | 8/5 | うどん | 鳥天 | NaN | 300 | 150.0 | NaN | 450 |
25 | 8/5 | そば | NaN | NaN | 300 | NaN | NaN | 300 |
26 | 8/6 | うどん | ゴボウ天 | NaN | 300 | 120.0 | NaN | 420 |
27 | 8/6 | うどん | 鳥天 | いなり | 300 | 150.0 | 100.0 | 550 |
28 | 8/6 | そば | イカ天 | NaN | 300 | 150.0 | NaN | 450 |
29 | 8/6 | そば | たまご | おにぎり | 300 | 50.0 | 100.0 | 450 |
pivot_table関数でindexを月日にして、columnsを麺にして合計金額の平均値をクロス集計しています。
udon.pivot_table(index='月日', columns='麺',values='合計金額')
結果
麺 | うどん | そば |
---|---|---|
月日 | ||
8/1 | 390.000000 | 485.0 |
8/2 | 430.000000 | 485.0 |
8/3 | 463.333333 | 400.0 |
8/4 | 466.666667 | 410.0 |
8/5 | 463.333333 | 300.0 |
8/6 | 485.000000 | 450.0 |
次の例は、indexを月日、columnsをトッピングにクロス集計した平均値です。
udon.pivot_table(index='月日', columns='トッピング',values='合計金額')
結果
トッピング | たまご | ちくわ天 | イカ天 | ゴボウ天 | 鳥天 |
---|---|---|---|---|---|
月日 | |||||
8/1 | 450.0 | 520.0 | 450.0 | 420.0 | NaN |
8/2 | 450.0 | 520.0 | NaN | 420.0 | 450.0 |
8/3 | 450.0 | NaN | 450.0 | 470.0 | NaN |
8/4 | NaN | 520.0 | NaN | NaN | 500.0 |
8/5 | NaN | NaN | NaN | 470.0 | 450.0 |
8/6 | 450.0 | NaN | 450.0 | 420.0 | 550.0 |
次の例はindexを麺にして、columnsをトッピングにして合計金額の合計をクロス集計しています。
udon.pivot_table(index='麺', columns='トッピング',values='合計金額',aggfunc=sum)
結果
トッピング | たまご | ちくわ天 | イカ天 | ゴボウ天 | 鳥天 |
---|---|---|---|---|---|
麺 | |||||
うどん | 450.0 | NaN | 450.0 | 3560.0 | 2450.0 |
そば | 1800.0 | 1560.0 | 900.0 | NaN | NaN |
コメントを投稿するにはログインしてください。