我有一个数据框,其中有一列称为动作,并带有字典列表。格式为{source:int,action:string},我需要将其解析为新的列,但是每个操作单元格中的记录数是可变的。
数据如下:
|Id |action |
|1 |[{"E": 4, "action": "views"}, {"A": 58, "action": "views"}]|
|2 |[{"A": 74, "action": "clicks"}] |
我希望它看起来像这样:
|Id|Source|Value|Action|
|1 |E |4 |views |
|1 |A |58 |views |
|2 |A |74 |clicks|
“操作”列中的词典数量最多为10
我已经尝试了几种解决方案,例如pandas DataFrame: normalize one JSON column and merge with other columns
但是它告诉我第一个解决方案没有正确调用DataFrame,而第二个解决方案的str没有属性值。甚至除此之外,这并不是我需要的解决方案,因为我需要重命名列源并将A / E / etc值放入其中。
答案 0 :(得分:2)
我将使用unnesting
yourdf=unnesting(df,['action']).reset_index(drop=True)
s=pd.DataFrame(yourdf.action.tolist()).reset_index().melt(['action','index']).dropna().set_index('index')
yourdf=pd.concat([yourdf,s],axis = 1)
yourdf
action ID action variable value
0 {'E': 4, 'action': 'views'} 1 views E 4.0
1 {'A': 58, 'action': 'views'} 1 views A 58.0
2 {'A': 74, 'action': 'clicks'} 2 clicks A 74.0
def unnesting(df, explode):
idx = df.index.repeat(df[explode[0]].str.len())
df1 = pd.concat([
pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
df1.index = idx
return df1.join(df.drop(explode, 1), how='left')
答案 1 :(得分:1)
只需使用列表理解来重建您的DataFrame数据:
更新:所以action
列是一个 string 字段,而不是Python数据结构。您可以使用 json.loads 对其进行预处理,这在从字符串中解析数据结构方面不易出错。
import json
# original dataframe
df = pd.DataFrame([
(1, '[{"E": 4, "action": "views"}, {"A": 58, "action": "views"}]')
, (2, '[{"A": 74, "action": "clicks"}]')
],
columns=['Id', 'action']
)
# new dataframe
df_new = pd.DataFrame(
[ (id, k, v, i['action']) for id,act in zip(df.Id, df.action.apply(json.loads))
for i in act
for k,v in i.items() if k != 'action'
],
columns=['Id', 'Source', 'Value', 'Action']
)
print(new_df)
# Id Source Value Action
#0 1 E 4 views
#1 1 A 58 views
#2 2 A 74 clicks
答案 2 :(得分:0)
我确实做了很长的路要走,但它可以为您提供所需的输出。我只是在数据框的列内嵌套字典。这仅在字典仅采用您在示例数据框中显示的格式时才有效。
import pandas as pd
df = pd.DataFrame({'id': [1,2],
'action': [[{"E": 4, "action": "views"},
{"A": 58, "action": "views"}],
[{"A": 74, "action": "clicks"}]]}
)
df_list = []
cols = ['id', 'source', 'value', 'action']
for x in df.index:
for actions in df.loc[x, 'action']:
row = []
row.append(df.loc[x,'id'])
for k,v in actions.items():
if k == 'action':
row.append(v)
else:
row.append(k)
row.append(v)
df_list.append(row)
test = pd.DataFrame(df_list, columns=cols)
哪个给出此输出
id source value action
0 1 E 4 views
1 1 A 58 views
2 2 A 74 clicks