概要
以下を横方向に展開したいときに、さっと検索しても方法が出てこなかったので、忘れそうなのでメモ
import pandas as pd
df=pd.Series([[1,2,3] for c in range(5)])
df
#0 [1, 2, 3]
#1 [1, 2, 3]
#2 [1, 2, 3]
#3 [1, 2, 3]
#4 [1, 2, 3]
#dtype: object
コード
リストを列方向に展開してバラす
pd.Series
をapply
するだけ
dfx=df.apply(pd.Series)
dfx
# 0 1 2
#0 1 2 3
#1 1 2 3
#2 1 2 3
#3 1 2 3
#4 1 2 3
※もし文字列のリストをバラしたい場合
df=pd.Series([["aa","bb","cc"] for c in range(5)])
df.apply(lambda x:" ".join(x)).str.split(expand=True)
※元が数字で、もし列にバラしたときに各列のデータ型が文字列型に変換されてもいいなら、" ".join(map(str,x)).str.split(expand=True)
とかにしてもいいかも
※そもそも元々がリストではなく分割できそうな文字列だった場合
df=pd.Series(["aa,bb,cc","dd,ee,ff","gg,hh,ii"])
df.str.split(pat=",",expand=True)
# 0 aa,bb,cc
# 1 dd,ee,ff
# 2 gg,hh,ii
# dtype: object
# 0 1 2
# 0 aa bb cc
# 1 dd ee ff
# 2 gg hh ii
列方向のデータをリストに集約する(元に戻す)
dfx.unstack().reset_index()
#列がlevel_0で行がlevel_1になって縦持ちデータに変換される
#columns.nameやindex.nameが設定されるとそれが反映される
# level_0 level_1 0
#0 0 0 1
#1 0 1 1
#2 0 2 1
#3 0 3 1
#4 0 4 1
#5 1 0 2
#6 1 1 2
#7 1 2 2
#8 1 3 2
#9 1 4 2
#10 2 0 3
#11 2 1 3
#12 2 2 3
#13 2 3 3
#14 2 4 3
dfx.unstack().reset_index().groupby("level_1")[0].apply(list) #または.agg(list)
#※カラムやSeriesのnameなどがリセットされるが、元の形には戻る。
#level_1
#0 [1, 2, 3]
#1 [1, 2, 3]
#2 [1, 2, 3]
#3 [1, 2, 3]
#4 [1, 2, 3]
#Name: 0, dtype: object
DataFrameで複数の列にリストが含まれているの場合
複数の列にそれぞれ列があるような場合は、
内包表記で各列に適用してあとでconcat
して横方向にくっつける。
もっといい方法ありそう…、誰か教えてください
df=pd.DataFrame([[[1,2,3],[1,2,3]] for c in range(5)])
df
# 0 1
#0 [1, 2, 3] [1, 2, 3]
#1 [1, 2, 3] [1, 2, 3]
#2 [1, 2, 3] [1, 2, 3]
#3 [1, 2, 3] [1, 2, 3]
#4 [1, 2, 3] [1, 2, 3]
dfx=pd.concat([df[x].apply(pd.Series) for x in df.columns],axis=1)
dfx
# 0 1 2 0 1 2
#0 1 2 3 1 2 3
#1 1 2 3 1 2 3
#2 1 2 3 1 2 3
#3 1 2 3 1 2 3
#4 1 2 3 1 2 3
参考
QAStack データフレームの行をパンダのグループでリストにグループ化する方法は? https://qastack.jp/programming/22219004/how-to-group-dataframe-rows-into-list-in-pandas-groupby