[英]Unpacking list of lists of dicts column in Pandas dataframe
我有df_in
其中一列是list
中lists
的dicts
:
df_in = pd.DataFrame({
'A': [1, 2, 3],
'B': [
[{'B1': 1, 'B2': 2, 'B3': 3}, {'B1': 4, 'B2': 5, 'B3': 6}, {'B1': 7, 'B2': 8, 'B3': 9}],
[{'B1': 10, 'B2': 11, 'B3': 12}],
[{'B1': 13, 'B2': 14, 'B3': 15}, {'B1': 16, 'B2': 17, 'B3': 18}]
],
'C': ['a', 'b', 'c']
})
df_in
A B C
0 1 [{'B1': 1, 'B2': 2, 'B3': 3}, {'B1': 4, 'B2': ... a
1 2 [{'B1': 10, 'B2': 11, 'B3': 12}] b
2 3 [{'B1': 13, 'B2': 14, 'B3': 15}, {'B1': 16, 'B... c
我想要實現的是解包B
的一般方法,以便 (1) 每個唯一鍵(在本例中為B1
、 B2
和B3
)都放入一列中。 並且 (2) 在每一行中堆疊多個列表作為新的觀察結果。 我認為示例輸出最好地解釋了這一點:
df_out = pd.DataFrame({
'A': [1, 1, 1, 2, 3, 3],
'B1': [1, 4, 7, 10, 13, 16],
'B2': [2, 5, 8, 11, 14, 17],
'B3': [3, 6, 9, 12, 15, 18],
'C': ['a', 'a', 'a', 'b', 'c', 'c']
})
df_out
A B1 B2 B3 C
0 1 1 2 3 a
1 1 4 5 6 a
2 1 7 8 9 a
3 2 10 11 12 b
4 3 13 14 15 c
5 3 16 17 18 c
有任何想法嗎?
使用帶有concat
和DataFrame.pop
字典理解來提取列:
df1 = pd.concat({k: pd.DataFrame(x) for k, x in df_in.pop('B').items()})
print (df1)
B1 B2 B3
0 0 1 2 3
1 4 5 6
2 7 8 9
1 0 10 11 12
2 0 13 14 15
1 16 17 18
通過DataFrame.join
添加原始數據並為正確的順序提取和附加C
列:
df = df_in.join(df1.reset_index(level=1, drop=True)).reset_index(drop=True)
df['C'] = df.pop('C')
print (df)
A B1 B2 B3 C
0 1 1 2 3 a
1 1 4 5 6 a
2 1 7 8 9 a
3 2 10 11 12 b
4 3 13 14 15 c
5 3 16 17 18 c
使用DataFrame.assign
替代解決方案,為了正確的順序使用DataFrame.insert
:
df1 = pd.concat([pd.DataFrame(v['B']).assign(A=v['A'], C=v['C'])
for k, v in df_in.to_dict('index').items()], ignore_index=True)
df1.insert(0, 'A', df1.pop('A'))
print (df1)
A B1 B2 B3 C
0 1 1 2 3 a
1 1 4 5 6 a
2 1 7 8 9 a
3 2 10 11 12 b
4 3 13 14 15 c
5 3 16 17 18 c
您可以嘗試df.explode
來df.explode
列表,然后將df_in
作為數據幀讀取並添加到df_in
:
df_in = df_in.explode('B')
df_out = pd.concat([df_in.reset_index(drop=True),
pd.DataFrame(df_in['B'].tolist())],
axis=1).drop('B', axis = 1).sort_index(axis=1)
df_out
A B1 B2 B3 C
0 1 1 2 3 a
1 1 4 5 6 a
2 1 7 8 9 a
3 2 10 11 12 b
4 3 13 14 15 c
5 3 16 17 18 c
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.