【问题标题】:Convert dataframe to JSON with 2 level nested array使用 2 级嵌套数组将数据帧转换为 JSON
【发布时间】:2018-12-20 15:09:32
【问题描述】:

我对 Python 编程有点陌生。我有一个小要求,我需要以 JSON 格式列出给定两周内的所有客户及其金额。

目前,我有一个这样的数据框:

  FortNight      Amount     Customer    Parameter
  Apr-2FN-2018   339632.00    10992     CustomerSales
  Apr-2FN-2018   27282.00     10994     CustomerSales 
  Apr-2FN-2018   26353.00     10995     CustomerSales 
  Apr-2FN-2018   24797.00     11000     CustomerSales
  Apr-2FN-2018   21093.00     10990     CustomerSales

预期的 JSON:

"CustomerSales" : [                                                                
    {"FortNight" : "Apr-2FN-2018",                                                                                      
         "Details" :[
             {"Customer":  "10992","Amount" : 339632.00},                                                                                                                                
             {"Customer":  "10994","Amount" : 27282.00},
             {"Customer":  "10995","Amount" : 26353.00},  
             {"Customer":  "11000","Amount" : 24797.00},
             {"Customer":  "10990","Amount" : 21093.00}
           ]
    }
]

我试过了:

dict(df.set_index('Parameter').groupby(level=0).apply(lambda  x : ast.literal_eval(x.to_json(orient = 'records', date_format = "iso"))))

它检索到这个:

 [{'CustomerSales': 
[{'Customer': '10992', 'Amount': 339632.00, 'FortNight': 'Apr-2FN-2018'}, {'Customer': '10994', 'Amount': 27282.00, 'FortNight': 'Apr-2FN-2018'},{'Customer': '10995', 'Amount': 26353.00, 'FortNight': 'Apr-2FN-2018'},
{'Customer': '11000', 'Amount': 24797.00, 'FortNight': 'Apr-2FN-2018'},
{'Customer': '10990', 'Amount': 21093.00, 'FortNight': 'Apr-2FN-2018'}]}]

我也尝试了其他方法,但徒劳无功。欢迎任何帮助。 提前致谢!

【问题讨论】:

  • 从不使用 ast.literal_eval() 解析 JSON。它速度较慢,并且在您具有布尔值或空值时会产生错误。此外,转换为 JSON 然后解析回字典意味着您真的只想生成一个字典,以更直接的路径开头。
  • 按该列分组时,您也不需要将索引设置为Parameter。只需使用df.groupby('Parameter')

标签: python json pandas dictionary


【解决方案1】:

首先对 Parameter FortNight 列进行分组,然后在生成的分组行上使用 .to_dict() 以生成最内层的字典:

details = df.groupby(['Parameter', 'FortNight']).apply(
    lambda r: r[['Customer', 'Amount']].to_dict(orient='records'))

这为您提供了一个在ParameterFortNight 上具有多索引的系列,并且值是正确格式的所有列表,每个条目都是一个包含CustomerAmount 列的字典。如果您需要转换值类型,请在调用to_dict() 之前对r[['Customer', 'Amount']] 数据帧结果执行此操作。

然后您可以将unstack 序列放入数据框,为您提供嵌套的 Parameter -> FortNight -> details 结构;参数值成为列,每个客户/金额字典列表由 FortNight 索引:

nested = details.unstack('Parameter')

如果你把它变成一本字典,你会得到一本已经基本正确的字典:

>>> pprint(grouped.unstack('Parameter').to_dict())
{'CustomerSales': {'Apr-2FN-2018': [{'Amount': 339632.0, 'Customer': '10992'},
                                    {'Amount': 27282.0, 'Customer': '10994'},
                                    {'Amount': 26353.0, 'Customer': '10995'},
                                    {'Amount': 24797.0, 'Customer': '11000'},
                                    {'Amount': 21093.0, 'Customer': '10990'}]}}

但对于您的格式,您需要将每列中的值转换为 {'FortNight': indexvalue, 'Details': value} 映射列表,然后将整个结构转换为字典:

output = nested.apply(lambda s: [
    {s.index.name: idx, 'Details': value}
    for idx, value in s.items()
]).to_dict('records')

这会给你最终的输出:

>>> pprint(output)
[{'CustomerSales': {'Details': [{'Amount': 339632.0, 'Customer': '10992'},
                                {'Amount': 27282.0, 'Customer': '10994'},
                                {'Amount': 26353.0, 'Customer': '10995'},
                                {'Amount': 24797.0, 'Customer': '11000'},
                                {'Amount': 21093.0, 'Customer': '10990'}],
                    'FortNight': 'Apr-2FN-2018'}}]

如果您需要 JSON 文档,请使用 .to_json(orient='records') 而不是 .to_dict('records')

组合成一个表达式:

df.groupby(['Parameter', 'FortNight']).apply(
        lambda r: r[['Customer', 'Amount']].to_dict(orient='records')
    ).unstack('Parameter').apply(lambda s: [
        {s.index.name: idx, 'Details': value}
        for idx, value in s.items()]
    ).to_json(orient='records')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 2018-05-15
    • 2021-04-13
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    相关资源
    最近更新 更多