[解決済み] データフレームをピボットするにはどうしたらいいですか?
質問
- ピボットとは何ですか?
- ピボットの方法を教えてください。
- これはピボットですか?
- 長尺物から幅広物へ?
ピボットテーブルについて尋ねる質問をよく見かけるようになりました。 ピボットテーブルについて尋ねていることに気づいていない場合でも、たいていはそうです。 ピボットテーブルのすべての側面を網羅する標準的な質問と回答を書くことは、事実上不可能です...
... でも、やってみようと思うんです。
既存の質問と回答の問題は、しばしば質問がニュアンスに集中しており、OPが既存の良い回答のいくつかを使用するために一般化するのに苦労していることである。 しかし、どの回答も包括的な説明をしようとはしていません(それは困難な作業であるため)。
私の Google検索
- 良い質問と回答です。 しかし、回答は具体的な質問に答えるだけで、ほとんど説明がない。
- この質問では、OP はピボットの出力に関心を寄せています。 つまり、列がどのように見えるかです。 OPは、Rのように見えることを望んでいました。これは、pandasユーザーにとってあまり有益ではありません。
-
もう一つのまともな質問ですが、答えは一つの方法、すなわち
pd.DataFrame.pivot
そのため、誰かが検索するたびに
pivot
その結果、特定の質問に答えられない可能性の高い、散発的な結果を得ることになります。
設定方法
以下の回答で、ピボットの方法に対応するために、列と関連する列の値に目立つ名前を付けていることにお気づきでしょうか。
import numpy as np
import pandas as pd
from numpy.core.defchararray import add
np.random.seed([3,1415])
n = 20
cols = np.array(['key', 'row', 'item', 'col'])
arr1 = (np.random.randint(5, size=(n, 4)) // [2, 1, 2, 1]).astype(str)
df = pd.DataFrame(
add(cols, arr1), columns=cols
).join(
pd.DataFrame(np.random.rand(n, 2).round(2)).add_prefix('val')
)
print(df)
key row item col val0 val1
0 key0 row3 item1 col3 0.81 0.04
1 key1 row2 item1 col2 0.44 0.07
2 key1 row0 item1 col0 0.77 0.01
3 key0 row4 item0 col2 0.15 0.59
4 key1 row0 item2 col1 0.81 0.64
5 key1 row2 item2 col4 0.13 0.88
6 key2 row4 item1 col3 0.88 0.39
7 key1 row4 item1 col1 0.10 0.07
8 key1 row0 item2 col4 0.65 0.02
9 key1 row2 item0 col2 0.35 0.61
10 key2 row0 item2 col1 0.40 0.85
11 key2 row4 item1 col2 0.64 0.25
12 key0 row2 item2 col3 0.50 0.44
13 key0 row4 item1 col4 0.24 0.46
14 key1 row3 item2 col3 0.28 0.11
15 key0 row3 item1 col1 0.31 0.23
16 key0 row0 item2 col3 0.86 0.01
17 key0 row4 item0 col3 0.64 0.21
18 key2 row2 item2 col0 0.13 0.45
19 key0 row2 item0 col4 0.37 0.70
質問(複数可)
-
が表示されるのはなぜですか?
ValueError: Index contains duplicate entries, cannot reshape
-
ピボットの方法
df
というようにcol
の値は列である。row
のインデックス、および平均値を表します。val0
は値ですか?col col0 col1 col2 col3 col4 row row0 0.77 0.605 NaN 0.860 0.65 row2 0.13 NaN 0.395 0.500 0.25 row3 NaN 0.310 NaN 0.545 NaN row4 NaN 0.100 0.395 0.760 0.24
-
ピボットの方法
df
というようにcol
の値は列である。row
の平均値はインデックスです。val0
は値、欠損値は0
?col col0 col1 col2 col3 col4 row row0 0.77 0.605 0.000 0.860 0.65 row2 0.13 0.000 0.395 0.500 0.25 row3 0.00 0.310 0.000 0.545 0.00 row4 0.00 0.100 0.395 0.760 0.24
-
以外のものを取得することは可能ですか?
mean
のような、もしかしたらsum
?col col0 col1 col2 col3 col4 row row0 0.77 1.21 0.00 0.86 0.65 row2 0.13 0.00 0.79 0.50 0.50 row3 0.00 0.31 0.00 1.09 0.00 row4 0.00 0.10 0.79 1.52 0.24
-
一度に複数のアグリゲーションを行うことはできますか?
sum mean col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4 row row0 0.77 1.21 0.00 0.86 0.65 0.77 0.605 0.000 0.860 0.65 row2 0.13 0.00 0.79 0.50 0.50 0.13 0.000 0.395 0.500 0.25 row3 0.00 0.31 0.00 1.09 0.00 0.00 0.310 0.000 0.545 0.00 row4 0.00 0.10 0.79 1.52 0.24 0.00 0.100 0.395 0.760 0.24
-
複数の値列を集約することはできますか?
val0 val1 col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4 row row0 0.77 0.605 0.000 0.860 0.65 0.01 0.745 0.00 0.010 0.02 row2 0.13 0.000 0.395 0.500 0.25 0.45 0.000 0.34 0.440 0.79 row3 0.00 0.310 0.000 0.545 0.00 0.00 0.230 0.00 0.075 0.00 row4 0.00 0.100 0.395 0.760 0.24 0.00 0.070 0.42 0.300 0.46
-
複数列での小分けは可能ですか?
item item0 item1 item2 col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4 row row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.605 0.86 0.65 row2 0.35 0.00 0.37 0.00 0.00 0.44 0.00 0.00 0.13 0.000 0.50 0.13 row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.000 0.28 0.00 row4 0.15 0.64 0.00 0.00 0.10 0.64 0.88 0.24 0.00 0.000 0.00 0.00
-
または
item item0 item1 item2 col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4 key row key0 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.86 0.00 row2 0.00 0.00 0.37 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.50 0.00 row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.00 0.00 0.00 row4 0.15 0.64 0.00 0.00 0.00 0.00 0.00 0.24 0.00 0.00 0.00 0.00 key1 row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.81 0.00 0.65 row2 0.35 0.00 0.00 0.00 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.13 row3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.28 0.00 row4 0.00 0.00 0.00 0.00 0.10 0.00 0.00 0.00 0.00 0.00 0.00 0.00 key2 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.40 0.00 0.00 row2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.13 0.00 0.00 0.00 row4 0.00 0.00 0.00 0.00 0.00 0.64 0.88 0.00 0.00 0.00 0.00 0.00
-
列と行が一緒に出現する頻度を集計する、いわゆるクロス集計は可能でしょうか?
col col0 col1 col2 col3 col4 row row0 1 2 0 1 1 row2 1 0 2 1 2 row3 0 1 0 2 0 row4 0 1 2 2 1
-
データフレームを2列のみでピボットしてロングからワイドに変換するにはどうすればよいですか?与えられた。
np.random.seed([3, 1415]) df2 = pd.DataFrame({'A': list('aaaabbbc'), 'B': np.random.choice(15, 8)}) df2 A B 0 a 0 1 a 11 2 a 2 3 a 11 4 b 10 5 b 10 6 b 14 7 c 7
期待されるのは次のようなものです。
a b c 0 0.0 10.0 7.0 1 11.0 10.0 NaN 2 2.0 14.0 NaN 3 11.0 NaN NaN
-
の後、複数のインデックスを単一インデックスにフラット化するにはどうすればよいですか?
pivot
?から
1 2 1 1 2 a 2 1 1 b 2 1 0 c 1 0 0
への
1|1 2|1 2|2 a 2 1 1 b 2 1 0 c 1 0 0
解決方法は?
まず、最初の質問に答えることから始めます。
質問1
なぜ
ValueError: Index contains duplicate entries, cannot reshape
この現象は、pandasが以下のいずれかのインデックスを再作成しようとしたために発生します。
columns
または
index
オブジェクトのエントリが重複している場合。 ピボットを実行するために使用するメソッドはさまざまです。 中には、ピボットを要求されるキーに重複がある場合に適さないものもあります。 たとえば、以下のような場合です。 を考えてみましょう。
pd.DataFrame.pivot
. を共有する重複したエントリーがあることは知っています。
row
と
col
の値を指定します。
df.duplicated(['row', 'col']).any()
True
そこで、私が
pivot
を使って
df.pivot(index='row', columns='col', values='val0')
上記のようなエラーが発生します。 実は、同じタスクを with で実行しようとすると、同じエラーが発生します。
df.set_index(['row', 'col'])['val0'].unstack()
以下は、ピボットに使えるイディオムのリストです。
-
pd.DataFrame.groupby
+pd.DataFrame.unstack
- あらゆるタイプのピボットを行うための一般的な方法です。
-
ピボットされた行レベルおよび列レベルを構成するすべての列を、1つのグループごとに指定します。 続いて、集約する残りの列と、集約を実行する関数を選択します。 最後に
unstack
は、列インデックスにしたいレベルを指定します。
-
-
の美化版。
groupby
より直感的なAPIで 多くの人にとって、これは好ましいアプローチです。 そして、開発者が意図したアプローチでもあります。 - 行レベル、列レベル、集約する値、および集約を実行する関数を指定します。
-
の美化版。
-
pd.DataFrame.set_index
+pd.DataFrame.unstack
- 便利で直感的な人もいる(私も含めて)。 グループ化されたキーの重複を扱えない。
-
と似ています。
groupby
パラダイムで、最終的に行レベルまたは列レベルになるすべての列を指定し、それらをインデックスに設定します。 次にunstack
には、列の中に必要なレベルを指定します。 残りのインデックスレベルまたはカラムレベルのいずれかが一意でない場合、このメソッドは失敗します。
-
-
と非常によく似ています。
set_index
重複キーの制限を共有している点です。 APIも非常に限定的である。 にはスカラー値しか使えない。index
,columns
,values
. -
と同様に
pivot_table
メソッドでは、ピボットの対象となる行、列、および値を選択します。 ただし、集約はできず、行または列のいずれかが一意でない場合、このメソッドは失敗します。
-
と非常によく似ています。
-
-
の特殊化バージョンです。
pivot_table
で、その最も純粋な形は、いくつかのタスクを実行するための最も直感的な方法です。
-
の特殊化バージョンです。
-
- これは非常に高度なテクニックで、非常にわかりにくいのですが、非常に速いです。 すべての状況で使用できるわけではありませんが、使用可能であり、使用に慣れている場合は、パフォーマンスの報酬を得ることができます。
-
pd.get_dummies
+pd.DataFrame.dot
- クロス集計を巧みに行うために使っています。
事例紹介
その後の回答や質問に対して行うのは
pd.DataFrame.pivot_table
. そして、同じタスクを実行するための代替手段を提供します。
質問3
<ブロッククオート
ピボットの方法
df
というように
col
の値は列である。
row
の平均値はインデックスです。
val0
は値で、欠損値は
0
?
-
-
fill_value
はデフォルトでは設定されていません。 適当に設定することが多いです。 この場合、私はこれを0
. をスキップしていることに注意してください。 質問2 を付けないと、この答えと同じになってしまうからです。fill_value
-
aggfunc='mean'
はデフォルトで、設定する必要はありませんでした。 明示的にするために入れました。df.pivot_table( values='val0', index='row', columns='col', fill_value=0, aggfunc='mean') col col0 col1 col2 col3 col4 row row0 0.77 0.605 0.000 0.860 0.65 row2 0.13 0.000 0.395 0.500 0.25 row3 0.00 0.310 0.000 0.545 0.00 row4 0.00 0.100 0.395 0.760 0.24
-
-
df.groupby(['row', 'col'])['val0'].mean().unstack(fill_value=0)
-
pd.crosstab( index=df['row'], columns=df['col'], values=df['val0'], aggfunc='mean').fillna(0)
質問4
以外のものを取得することは可能ですか?
mean
のような、もしかしたらsum
?
-
df.pivot_table( values='val0', index='row', columns='col', fill_value=0, aggfunc='sum') col col0 col1 col2 col3 col4 row row0 0.77 1.21 0.00 0.86 0.65 row2 0.13 0.00 0.79 0.50 0.50 row3 0.00 0.31 0.00 1.09 0.00 row4 0.00 0.10 0.79 1.52 0.24
-
df.groupby(['row', 'col'])['val0'].sum().unstack(fill_value=0)
-
pd.crosstab( index=df['row'], columns=df['col'], values=df['val0'], aggfunc='sum').fillna(0)
質問5
一度に複数の集計を行うことはできますか?
について注目してください。
pivot_table
と
crosstab
callableのリストを渡す必要がありました。 一方
groupby.agg
は、限られた特殊な関数のために文字列を取ることができます。
groupby.agg
も他の人に渡したのと同じcallableを取ることができましたが、文字列関数名を活用した方が効率的なことが多いので、文字列関数名を活用することにしました。
-
df.pivot_table( values='val0', index='row', columns='col', fill_value=0, aggfunc=[np.size, np.mean]) size mean col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4 row row0 1 2 0 1 1 0.77 0.605 0.000 0.860 0.65 row2 1 0 2 1 2 0.13 0.000 0.395 0.500 0.25 row3 0 1 0 2 0 0.00 0.310 0.000 0.545 0.00 row4 0 1 2 2 1 0.00 0.100 0.395 0.760 0.24
-
df.groupby(['row', 'col'])['val0'].agg(['size', 'mean']).unstack(fill_value=0)
-
pd.crosstab( index=df['row'], columns=df['col'], values=df['val0'], aggfunc=[np.size, np.mean]).fillna(0, downcast='infer')
質問6
複数の値列を集約することはできますか?
-
pd.DataFrame.pivot_table
私たちはvalues=['val0', 'val1']
しかし、これは完全に除外することができます。df.pivot_table( values=['val0', 'val1'], index='row', columns='col', fill_value=0, aggfunc='mean') val0 val1 col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4 row row0 0.77 0.605 0.000 0.860 0.65 0.01 0.745 0.00 0.010 0.02 row2 0.13 0.000 0.395 0.500 0.25 0.45 0.000 0.34 0.440 0.79 row3 0.00 0.310 0.000 0.545 0.00 0.00 0.230 0.00 0.075 0.00 row4 0.00 0.100 0.395 0.760 0.24 0.00 0.070 0.42 0.300 0.46
-
df.groupby(['row', 'col'])['val0', 'val1'].mean().unstack(fill_value=0)
質問7
複数列での小分けは可能ですか?
-
df.pivot_table( values='val0', index='row', columns=['item', 'col'], fill_value=0, aggfunc='mean') item item0 item1 item2 col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4 row row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.605 0.86 0.65 row2 0.35 0.00 0.37 0.00 0.00 0.44 0.00 0.00 0.13 0.000 0.50 0.13 row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.000 0.28 0.00 row4 0.15 0.64 0.00 0.00 0.10 0.64 0.88 0.24 0.00 0.000 0.00 0.00
-
df.groupby( ['row', 'item', 'col'] )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
質問8
複数列での小分けは可能ですか?
-
df.pivot_table( values='val0', index=['key', 'row'], columns=['item', 'col'], fill_value=0, aggfunc='mean') item item0 item1 item2 col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4 key row key0 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.86 0.00 row2 0.00 0.00 0.37 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.50 0.00 row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.00 0.00 0.00 row4 0.15 0.64 0.00 0.00 0.00 0.00 0.00 0.24 0.00 0.00 0.00 0.00 key1 row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.81 0.00 0.65 row2 0.35 0.00 0.00 0.00 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.13 row3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.28 0.00 row4 0.00 0.00 0.00 0.00 0.10 0.00 0.00 0.00 0.00 0.00 0.00 0.00 key2 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.40 0.00 0.00 row2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.13 0.00 0.00 0.00 row4 0.00 0.00 0.00 0.00 0.00 0.64 0.88 0.00 0.00 0.00 0.00 0.00
-
df.groupby( ['key', 'row', 'item', 'col'] )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
-
pd.DataFrame.set_index
なぜなら、キーのセットは行と列の両方で一意だからです。df.set_index( ['key', 'row', 'item', 'col'] )['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
質問9
列と行が一緒に出現する頻度を集計する、いわゆるクロス集計は可能ですか?
-
df.pivot_table(index='row', columns='col', fill_value=0, aggfunc='size') col col0 col1 col2 col3 col4 row row0 1 2 0 1 1 row2 1 0 2 1 2 row3 0 1 0 2 0 row4 0 1 2 2 1
-
df.groupby(['row', 'col'])['val0'].size().unstack(fill_value=0)
-
pd.crosstab(df['row'], df['col'])
-
# get integer factorization `i` and unique values `r` # for column `'row'` i, r = pd.factorize(df['row'].values) # get integer factorization `j` and unique values `c` # for column `'col'` j, c = pd.factorize(df['col'].values) # `n` will be the number of rows # `m` will be the number of columns n, m = r.size, c.size # `i * m + j` is a clever way of counting the # factorization bins assuming a flat array of length # `n * m`. Which is why we subsequently reshape as `(n, m)` b = np.bincount(i * m + j, minlength=n * m).reshape(n, m) # BTW, whenever I read this, I think 'Bean, Rice, and Cheese' pd.DataFrame(b, r, c) col3 col2 col0 col1 col4 row3 2 0 0 1 0 row2 1 2 1 0 2 row0 1 0 1 2 1 row4 2 2 0 1 1
-
pd.get_dummies(df['row']).T.dot(pd.get_dummies(df['col'])) col0 col1 col2 col3 col4 row0 1 2 0 1 1 row2 1 0 2 1 2 row3 0 1 0 2 0 row4 0 1 2 2 1
質問10
データフレームをロングからワイドに変換するには、2つのピボットを使用します。 列は?
-
まず、各行に番号を割り当てます。この番号は、回転させた結果におけるその値の行インデックスとなります。これは
GroupBy.cumcount
:df2.insert(0, 'count', df2.groupby('A').cumcount()) df2 count A B 0 0 a 0 1 1 a 11 2 2 a 2 3 3 a 11 4 0 b 10 5 1 b 10 6 2 b 14 7 0 c 7
2 番目のステップでは、新しく作成されたカラムをインデックスとして使用して
DataFrame.pivot
.df2.pivot(*df2) # df2.pivot(index='count', columns='A', values='B') A a b c count 0 0.0 10.0 7.0 1 11.0 10.0 NaN 2 2.0 14.0 NaN 3 11.0 NaN NaN
-
一方
DataFrame.pivot
はカラムのみ受け付けます。DataFrame.pivot_table
は配列も受け付けるのでGroupBy.cumcount
として直接渡すことができます。index
は、明示的にカラムを作成することなくdf2.pivot_table(index=df2.groupby('A').cumcount(), columns='A', values='B') A a b c 0 0.0 10.0 7.0 1 11.0 10.0 NaN 2 2.0 14.0 NaN 3 11.0 NaN NaN
質問11
の後、マルチインデックスをシングルインデックスにフラット化するにはどうすればよいですか?
pivot
もし
columns
タイプ
object
文字列付き
join
df.columns = df.columns.map('|'.join)
さもなくば
format
df.columns = df.columns.map('{0[0]}|{0[1]}'.format)
関連
-
[解決済み】RuntimeWarning: 割り算で無効な値が発生しました。
-
[解決済み】「OverflowError: Python int too large to convert to C long" on windows but not mac
-
[解決済み] プログラムの実行やシステムコマンドの呼び出しはどのように行うのですか?
-
[解決済み] Pythonで辞書に新しいキーを追加するにはどうすればよいですか?
-
[解決済み] PandasでDataFrameの行を反復処理する方法
-
[解決済み] ファイルのコピー方法について教えてください。
-
[解決済み] 列の値に基づいてDataFrameから行を選択するにはどうすればよいですか?
-
[解決済み] Pandas DataFrameからカラムを削除する
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】2つの辞書を1つの式でマージする(辞書の和をとる)には?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python関数の高度な応用を解説
-
python implement mysql add delete check change サンプルコード
-
Python 可視化 big_screen ライブラリ サンプル 詳細
-
風力制御におけるKS原理を深く理解するためのpythonアルゴリズム
-
[解決済み】RuntimeWarning: 割り算で無効な値が発生しました。
-
[解決済み】numpy: true_divide で無効な値に遭遇
-
[解決済み】socket.error: [Errno 48] アドレスはすでに使用中です。
-
[解決済み】TypeError: 系列を <class 'float'> に変換することができません。
-
[解決済み】Python Error: "ValueError: need more than 1 value to unpack" (バリューエラー:解凍に1つ以上の値が必要です
-
[解決済み] Pandasでデータフレームをピボットする方法は?重複