以下図のように、PandasのDataFrameを横長のシートに変換したいと思っております。
for文を使うのは一つかと思いますが、実際はアイテム数も大きいので、標準メソッドで実施したいと思っています。
何かしらよいメソッドはありますでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
df.pivot()
を用いるのが簡便かと思われます。
pandas.DataFrame.pivot — pandas 1.0.2 documentation
また、id1
・id2
列がインデックスに設定されている場合は、df.unstack()
を用いることができます。
pandas.DataFrame.unstack — pandas 1.0.2 documentation
ケース1
python
1data = {'id1': [1, 1, 1, 2, 2, 2], 2 'id2': [1, 2, 3, 1, 2, 3], 3 'item1': [1, 4, 7, 1, 4, 7], 4 'item2': [2, 5, 8, 2, 5, 8], 5 'item3': [3, 6, 9, 3, 6, 9]} 6df = pd.DataFrame(data) 7print(df)
id1 | id2 | item1 | item2 | item3 | |
---|---|---|---|---|---|
0 | 1 | 1 | 1 | 2 | 3 |
1 | 1 | 2 | 4 | 5 | 6 |
2 | 1 | 3 | 7 | 8 | 9 |
3 | 2 | 1 | 1 | 2 | 3 |
4 | 2 | 2 | 4 | 5 | 6 |
5 | 2 | 3 | 7 | 8 | 9 |
このとき、
python
1new_df = df.pivot('id1', 'id2') 2print(new_df)
id1 | ('item1', 1) | ('item1', 2) | ('item1', 3) | ('item2', 1) | ('item2', 2) | ('item2', 3) | ('item3', 1) | ('item3', 2) | ('item3', 3) |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | 4 | 7 | 2 | 5 | 8 | 3 | 6 | 9 |
2 | 1 | 4 | 7 | 2 | 5 | 8 | 3 | 6 | 9 |
質問にある例と全く同一の形式に変換するには、
python
1new_df = df.pivot('id1', 'id2') 2new_df.sort_index(axis=1, level=1, inplace=True) 3new_df.set_axis(['-'.join([c1, str(c2)]) for c1, c2 in new_df.columns], 4 axis=1, inplace=True) 5print(new_df)
id1 | item1-1 | item2-1 | item3-1 | item1-2 | item2-2 | item3-2 | item1-3 | item2-3 | item3-3 |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
2 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
ケース2(id
列がindexのとき)
python
1data = {'id1': [1, 1, 1, 2, 2, 2], 2 'id2': [1, 2, 3, 1, 2, 3], 3 'item1': [1, 4, 7, 1, 4, 7], 4 'item2': [2, 5, 8, 2, 5, 8], 5 'item3': [3, 6, 9, 3, 6, 9]} 6df = pd.DataFrame(data).set_index(['id1', 'id2']) 7print(df)
item1 | item2 | item3 | |
---|---|---|---|
(1, 1) | 1 | 2 | 3 |
(1, 2) | 4 | 5 | 6 |
(1, 3) | 7 | 8 | 9 |
(2, 1) | 1 | 2 | 3 |
(2, 2) | 4 | 5 | 6 |
(2, 3) | 7 | 8 | 9 |
このとき、
python
1new_df = df.unstack() 2new_df.sort_index(axis=1, level=1, inplace=True) 3new_df.set_axis(['-'.join([c1, str(c2)]) for c1, c2 in new_df.columns], 4 axis=1, inplace=True) 5print(new_df)
id1 | item1-1 | item2-1 | item3-1 | item1-2 | item2-2 | item3-2 | item1-3 | item2-3 | item3-3 |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
2 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
ケース3(NumPyを使う方法)
id1
・id2
列がインデックスに設定されていて、id1
とid2
の組み合わせが全て網羅されている場合、33ブロックを19に組み替えるだけでいいので、以下の方法が使えます。
python
1data = {'id1': [1, 1, 1, 2, 2, 2], 2 'id2': [1, 2, 3, 1, 2, 3], 3 'item1': [1, 4, 7, 1, 4, 7], 4 'item2': [2, 5, 8, 2, 5, 8], 5 'item3': [3, 6, 9, 3, 6, 9]} 6df = pd.DataFrame(data).set_index(['id1', 'id2']) 7# ケース2と同じ
このとき、
python
1# NumPy配列に変換 2arr = df.to_numpy() 3# もし、'id1', 'id2'の組み合わせが網羅的でなく、ソートされていない場合(例えば、 4print(df.sample(frac=0.9, random_state=0)) 5# item1 item2 item3 6# id1 id2 7# 2 2 4 5 6 8# 1 1 2 3 9# 3 7 8 9 10# 1 3 7 8 9 11# 3 1 1 2 3 12# 3 7 8 9 13# 1 2 4 5 6 のようなとき) 14# 'id1', 'id2'の組み合わせを網羅させ、NumPy配列に変換 15arr = df.reindex(pd.MultiIndex.from_product(df.index.levels)).to_numpy() 16 17# `ndarray.reshape()`を用いて組み換え、データフレームに変換 18col = pd.MultiIndex.from_product((df.index.levels[1], df.columns)) 19new_df = pd.DataFrame(arr.reshape(df.index.levshape[0], -1), 20 index=df.index.levels[0], columns=col) 21 22new_df.set_axis(['-'.join([c1, str(c2)]) for c1, c2 in new_df.columns], 23 axis=1, inplace=True) 24print(new_df)
id1 | item1-1 | item2-1 | item3-1 | item1-2 | item2-2 | item3-2 | item1-3 | item2-3 | item3-3 |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
2 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
投稿2020/03/16 01:21
編集2020/03/16 05:01総合スコア1399
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。