Pandas:如何规范化具有多个 JSON 嵌套列表的 JSON 文件?
Posted
技术标签:
【中文标题】Pandas:如何规范化具有多个 JSON 嵌套列表的 JSON 文件?【英文标题】:Pandas: How do I normalize a JSON file with multiple nested lists of JSON? 【发布时间】:2021-11-22 14:40:15 【问题描述】:我从 API 请求数据,然后尝试规范化这个 JSON 文件,它有这个结构
['la_id': '33',
'store': '1405fdsa6001209',
'sell': '110aa346',
'products': ['codigo': '176690', 'lacre': '15980fd2293', 'valor': '49.90',
'codigo': 'sd4907', 'lacre': '1598a12385', 'valor': '19.90',
'codigo': 'aa4907', 'lacre': '1598a2384', 'valor': '19.90',
'codigo': '1fd307', 'lacre': '1598a20401', 'valor': '169.90'],
'payment': 'paymentid': '10a836',
'value': '259.6000',
'number': '4',
'finalid': '4',
'finalname': 'Cartao de credito',
'docs': '849763',
'flag': None
'pagamentos': ['pagamento_id': '107795',
'valor': '854.9900',
'numero_parcelas': '10',
'finalizador_id': '4',
'finalizador_nome': 'Cartao de credito',
'documento': '500003',
'bandeira': 'MASTERCARD']
当我应用 JsonNormalize 以将其转换为数据框时,我得到了这个:
id | store | sell | products | pagamentos |
---|---|---|---|---|
33 | 1405fdsa6001209 | 110aa346 | ['codigo': '176690', 'lacre': '15980fd2293', 'valor': '49.90', 'codigo': 'sd4907', 'lacre': '1598a12385', 'valor': '19.90', 'codigo': 'aa4907', 'lacre': '1598a2384', 'valor': '19.90', 'codigo': '1fd307', 'lacre': '1598a20401', 'valor': '169.90'] | ['pagamento_id': '10aa95','valor': '84.9900','numero_parcelas': '10','finalizador_id': '4','finalizador_nome': 'Cartao de credito','docs': '500003','bandeira': 'MASTERCARD'] |
如您所见,最后两列没有正确获取值,它们在列表中有字典。我该如何解决这个问题?
【问题讨论】:
1) 发布一个有效的 JSON 结构。 2)规范化JSONmanualy并分享结果 @Leonardo 请添加“|”表格第二行中用于格式化表格的符号 更新了我的解决方案以获得额外的pagamentos
。请看一看。
【参考方案1】:
试试:
lst = [
"la_id": "33",
"store": "1405fdsa6001209",
"sell": "110aa346",
"products": [
"codigo": "176690", "lacre": "15980fd2293", "valor": "49.90",
"codigo": "sd4907", "lacre": "1598a12385", "valor": "19.90",
"codigo": "aa4907", "lacre": "1598a2384", "valor": "19.90",
"codigo": "1fd307", "lacre": "1598a20401", "valor": "169.90",
],
"payment":
"paymentid": "10a836",
"value": "259.6000",
"number": "4",
"finalid": "4",
"finalname": "Cartao de credito",
"docs": "849763",
"flag": None,
,
]
df = pd.json_normalize(lst).explode("products")
df = pd.concat([df, df.pop("products").apply(pd.Series)], axis=1)
print(df)
打印:
la_id store sell payment.paymentid payment.value payment.number payment.finalid payment.finalname payment.docs payment.flag codigo lacre valor
0 33 1405fdsa6001209 110aa346 10a836 259.6000 4 4 Cartao de credito 849763 None 176690 15980fd2293 49.90
0 33 1405fdsa6001209 110aa346 10a836 259.6000 4 4 Cartao de credito 849763 None sd4907 1598a12385 19.90
0 33 1405fdsa6001209 110aa346 10a836 259.6000 4 4 Cartao de credito 849763 None aa4907 1598a2384 19.90
0 33 1405fdsa6001209 110aa346 10a836 259.6000 4 4 Cartao de credito 849763 None 1fd307 1598a20401 169.90
编辑:更新输入:
df = pd.concat([df, df.pop("payments").apply(pd.Series)], axis=1)
df = df.explode("product")
df = pd.concat([df, df.pop("product").apply(pd.Series)], axis=1)
print(df)
打印:
id store sell payment_id valor number finalid finalizador_nome docs flag codigo lacre valor
0 33 1405fdsa6001209 110aa346 10aa95 84.9900 10 4 Cartao de credito 500003 MASTERCARD 176690 15980fd2293 49.90
0 33 1405fdsa6001209 110aa346 10aa95 84.9900 10 4 Cartao de credito 500003 MASTERCARD sd4907 1598a12385 19.90
0 33 1405fdsa6001209 110aa346 10aa95 84.9900 10 4 Cartao de credito 500003 MASTERCARD aa4907 1598a2384 19.90
0 33 1405fdsa6001209 110aa346 10aa95 84.9900 10 4 Cartao de credito 500003 MASTERCARD 1fd307 1598a20401 169.90
【讨论】:
哦!凉爽的!在我的情况下,我还有另一个具有相同问题的列(我没有在示例中放入的付款列)如何“爆炸”两个列的值?我在这里尝试将两者都放入公式中,但没有奏效 @LeonardoAmador 您能否编辑您的问题并更新示例输入? 是的,当然,我刚刚这样做了 好像新添加的标签是pagamentos
:-)
非常感谢!【参考方案2】:
您可以为每个使用pd.json_normalize()
:
提取主要字段(包括键la_id
)
提取products
详细信息+密钥la_id
提取pagamentos
详细信息+密钥la_id
然后,使用.merge()
,使用公共键la_id
合并3个结果数据帧,如下:
j_lst = ['la_id': '33',
'store': '1405fdsa6001209',
'sell': '110aa346',
'products': ['codigo': '176690', 'lacre': '15980fd2293', 'valor': '49.90',
'codigo': 'sd4907', 'lacre': '1598a12385', 'valor': '19.90',
'codigo': 'aa4907', 'lacre': '1598a2384', 'valor': '19.90',
'codigo': '1fd307', 'lacre': '1598a20401', 'valor': '169.90'],
'payment': 'paymentid': '10a836',
'value': '259.6000',
'number': '4',
'finalid': '4',
'finalname': 'Cartao de credito',
'docs': '849763',
'flag': None,
'pagamentos': ['pagamento_id': '107795',
'valor': '854.9900',
'numero_parcelas': '10',
'finalizador_id': '4',
'finalizador_nome': 'Cartao de credito',
'documento': '500003',
'bandeira': 'MASTERCARD']]
df_main = pd.json_normalize(j_lst)
df_products = pd.json_normalize(j_lst, record_path=['products'], record_prefix='products.', meta=['la_id'])
df_pagamentos = pd.json_normalize(j_lst, record_path=['pagamentos'], record_prefix='pagamentos.', meta=['la_id'])
df_out = (df_main.merge(df_products, on='la_id')
.merge(df_pagamentos, on='la_id')
.drop(['products', 'pagamentos'], axis=1)
)
结果:
print(df_out)
la_id store sell payment.paymentid payment.value payment.number payment.finalid payment.finalname payment.docs payment.flag products.codigo products.lacre products.valor pagamentos.pagamento_id pagamentos.valor pagamentos.numero_parcelas pagamentos.finalizador_id pagamentos.finalizador_nome pagamentos.documento pagamentos.bandeira
0 33 1405fdsa6001209 110aa346 10a836 259.6000 4 4 Cartao de credito 849763 None 176690 15980fd2293 49.90 107795 854.9900 10 4 Cartao de credito 500003 MASTERCARD
1 33 1405fdsa6001209 110aa346 10a836 259.6000 4 4 Cartao de credito 849763 None sd4907 1598a12385 19.90 107795 854.9900 10 4 Cartao de credito 500003 MASTERCARD
2 33 1405fdsa6001209 110aa346 10a836 259.6000 4 4 Cartao de credito 849763 None aa4907 1598a2384 19.90 107795 854.9900 10 4 Cartao de credito 500003 MASTERCARD
3 33 1405fdsa6001209 110aa346 10a836 259.6000 4 4 Cartao de credito 849763 None 1fd307 1598a20401 169.90 107795 854.9900 10 4 Cartao de credito 500003 MASTERCARD
【讨论】:
以上是关于Pandas:如何规范化具有多个 JSON 嵌套列表的 JSON 文件?的主要内容,如果未能解决你的问题,请参考以下文章
使用 JSON 对象展开 Pandas DataFrame 列