[英]Convert pandas df to a dictionary
我需要轉換以下格式的 df:
d = {
'A': ['a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'a2', 'a2', 'a2', 'a2', 'a2', 'a2', 'a2', 'a2'],
'B': ['b1', 'b1', 'b1', 'b1', 'b2', 'b2', 'b2', 'b3', 'b3', 'b3', 'b3', 'b3', 'b3', 'b4', 'b4', ],
'C': ['c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10', 'c11', 'c12', 'c13', 'c14', 'c15', ],
}
df = pd.DataFrame(d)
df
A B C
0 a1 b1 c1
1 a1 b1 c2
2 a1 b1 c3
3 a1 b1 c4
4 a1 b2 c5
5 a1 b2 c6
6 a1 b2 c7
7 a2 b3 c8
8 a2 b3 c9
9 a2 b3 c10
10 a2 b3 c11
11 a2 b3 c12
12 a2 b3 c13
13 a2 b4 c14
14 a2 b4 c15
到以下格式的字典:
outDict = {
'a1': {
'b1': ['c1', 'c2', 'c3', 'c4'],
'b2': ['c5', 'c6', 'c7'],
},
'a2': {
'b3': ['c8', 'c9', 'c10', 'c11', 'c12', 'c13'],
'b4': ['c14', 'c15'],
}
}
即 A 列中的值成為第一級鍵; B 列二級鍵中的值和 C 列中的值是一個列表。
任何指針?
這是使用pivot_table
另一種方法:
out = {k:v.dropna().to_dict() for k,v in
df.pivot_table('C','B','A',aggfunc=list).items()}
{'a1': {'b1': ['c1', 'c2', 'c3', 'c4'], 'b2': ['c5', 'c6', 'c7']},
'a2': {'b3': ['c8', 'c9', 'c10', 'c11', 'c12', 'c13'], 'b4': ['c14', 'c15']}}
這會有點長,我敢說:
new_dict = {k: v['C'] for k,v in df.groupby(['A', 'B'])
.agg(list).groupby(level=0)
.apply(lambda df: df.xs(df.name)
.to_dict()).to_dict().items()}
print(new_dict)
輸出:
{
'a1': {
'b1': ['c1', 'c2', 'c3', 'c4'],
'b2': ['c5', 'c6', 'c7'],
},
'a2': {
'b3': ['c8', 'c9', 'c10', 'c11', 'c12', 'c13'],
'b4': ['c14', 'c15'],
}
}
開箱:
>>> df.groupby(['A', 'B']).agg(list)
C
A B
a1 b1 [c1, c2, c3, c4]
b2 [c5, c6, c7]
a2 b3 [c8, c9, c10, c11, c12, c13]
b4 [c14, c15]
>>> df.groupby(['A', 'B']).agg(list).groupby(level=0).apply(lambda df: df.xs(df.name).to_dict())
# we groupby level 0 again, then call xs as aggregator function to access each key
# in level 0, and convert to dict
A
a1 {'C': {'b1': ['c1', 'c2', 'c3', 'c4'], 'b2': [...
a2 {'C': {'b3': ['c8', 'c9', 'c10', 'c11', 'c12',...
dtype: object
>>> df.groupby(['A', 'B']).agg(list).groupby(level=0).apply(lambda df: df.xs(df.name).to_dict()).to_dict()
{'a1': {'C': {'b1': ['c1', 'c2', 'c3', 'c4'], 'b2': ['c5', 'c6', 'c7']}},
'a2': {'C': {'b3': ['c8', 'c9', 'c10', 'c11', 'c12', 'c13'],
'b4': ['c14', 'c15']}}}
# then just using dict comp to remove column name 'C'
遞歸解決方案似乎很自然並且適用於任意數量的列。 我們對最左邊的列進行groupby
,並遞歸地將剩余的列轉換為所需的格式。 如果只剩下一列,則返回一個列表。
def df2dict_rec(df):
if df.shape[1] == 1:
return df.values[:,0].tolist()
else:
return {k: df2dict_rec(df_k.iloc[:,1:]) for k, df_k in df.groupby(df.columns[0])}
res = df2dict_rec(df)
# {'a1': {'b1': ['c1', 'c2', 'c3', 'c4'], 'b2': ['c5', 'c6', 'c7']},
# 'a2': {'b3': ['c8', 'c9', 'c10', 'c11', 'c12', 'c13'], 'b4': ['c14', 'c15']}}
歡迎任何改進
dictLevel1 = {}
dictLevel2 = {}
for b,c in zip(list(df['B']),list(df['C'])):
try:
dictLevel2[b].append(c)
except KeyError:
dictLevel2[b] = [c]
for a,b in zip(list(df['A']),list(df['B'])):
try:
dictLevel1[a].update({b:dictLevel2[b]})
except:
dictLevel1[a] = {b: dictLevel2[b]}
print(dictLevel1)
輸出
{'a1': {'b1': ['c1', 'c2', 'c3', 'c4'], 'b2': ['c5', 'c6', 'c7']}, 'a2': {'b3': ['c8', 'c9', 'c10', 'c11', 'c12', 'c13'], 'b4': ['c14', 'c15']}}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.