【问题标题】:Output pandas dataframe as a multi level python dictionary to support API JSON request将 pandas 数据帧输出为多级 python 字典以支持 API JSON 请求
【发布时间】:2021-10-28 12:07:53
【问题描述】:

我有一个将时间序列数据作为 JSON 请求提取的 API,并且需要以下格式的 JSON:

[
{
    "ts": 1630116000000,
    "values": {
        "vwc1": 1.69,
        "vwc2": 1.93
        ...
    }
},
{
    "ts": 163015600000,
    "values": {
        "vwc1": 1.59,
        "vwc2": 1.97
    }
}
]

源数据以 csv 格式导入 python 并放入 pandas 数据框:

                             vsys     vup      vwc1      vic1       st1      vwc2      vic2       st2      vwc3      vic3       st3      ...             st9     vwc10     vic10      st10     vwc11     vic11      st11     vwc12     vic12      st12             ts
Date Time                                                                                                                                ...                                                                                                                         
2021-08-28 12:00:00+10:00  13.350  13.348  11.38990  1691.903  19.00000  19.18203  400.4311  18.78000  19.68363  1211.360  18.91000      ...        20.89001  43.59949  1874.603  19.91000  43.66155  21054.63  19.79999  47.13536  4195.486  19.97000  1630116000000
2021-08-28 12:30:00+10:00  13.360  -1.000  11.34434  1683.595  19.10999  19.17777  400.8896  18.72000  19.67229  1211.366  18.89999      ...        20.82999  43.55956  1874.017  19.98999  43.65295  20977.79  19.79999  47.10374  4193.230  20.07001  1630117800000
2021-08-28 13:00:00+10:00  13.371  -1.000  11.30646  1733.315  19.23001  19.14365  404.5721  18.82999  19.65718  1215.523  18.92001      ...        20.91000  43.55956  1874.017  20.01001  43.67014  20995.88  19.75000  47.10374  4193.230  20.07001  1630119600000

我大部分时间都在尝试让我的脚本将源数据输出为正确的 JSON(嵌套字典)格式。我查看了 to_dict 和 groupby 并开发了以下代码:

cols = df.columns.difference(['ts'])
    payload = (df.groupby(['ts'])[cols]
        .apply(lambda x: x.to_dict(orient='records'))
        .reset_index(name='values')
        .to_dict(orient='records'))

这会产生非常接近我需要的东西:

[
    {
        "ts": 1630116000000,
        "values": [
            {
                "vwc1": 11.3899,
                "vwc2": 19.182029999999997
            }
        ]
    },
    {
        "ts": 1630117800000,
        "values": [
            {
                "vwc1": 11.344339999999999,
                "vwc2": 19.177770000000002
            }
        ]
    },
    {
        "ts": 1630119600000,
        "values": [
            {
                "vwc1": 11.306460000000001,
                "vwc2": 19.14365,
            }
        ]
    }
]

但杀手锏是 'values' 对象被生成为一个字典对象列表,而不仅仅是一个普通字典(这是 API 所要求的根据上面的示例 JSON)。

我已经阅读了 to_dict 方法,觉得问题可能出在方法的 orient 参数上,但我终其一生都无法做到。

欢迎提出任何建议。

【问题讨论】:

    标签: python pandas dataframe dictionary pandas-groupby


    【解决方案1】:

    来自您的DataFrame

    import pandas as pd
    from io import StringIO
    
    df = pd.read_csv(StringIO("""
    Date Time,vsys,vup,vwc1,vic1,st1,vwc2,ts
    2021-08-28 12:00:00+10:00,13.350,13.348,11.38990,1691.903,19.00000,19.18203,1630116000000
    2021-08-28 12:30:00+10:00,13.360,-1.000,11.34434,1683.595,19.10999,19.17777,1630117800000  
    2021-08-28 13:00:00+10:00,13.371,-1.000,11.30646,1733.315,19.23001,19.14365,1630119600000"""))
    df = df.set_index(['Date Time'])
    

    我们可以使用tuple并提取其中的唯一值来避免list格式并得到预期的结果:

    >>> cols = df.columns.difference(['ts'])
    >>> payload = (df.groupby(['ts'])[cols]
    ...     .apply(lambda x: tuple(x.to_dict(orient='records'))[0])
    ...     .reset_index(name='values')
    ...     .to_dict(orient='records'))
    >>> payload
    [{'ts': 1630116000000,
      'values': {'st1': 19.0,
       'vic1': 1691.903,
       'vsys': 13.35,
       'vup': 13.348,
       'vwc1': 11.3899,
       'vwc2': 19.18203}},
     {'ts': 1630117800000,
      'values': {'st1': 19.10999,
       'vic1': 1683.595,
       'vsys': 13.36,
       'vup': -1.0,
       'vwc1': 11.34434,
       'vwc2': 19.17777}},
     {'ts': 1630119600000,
      'values': {'st1': 19.23001,
       'vic1': 1733.315,
       'vsys': 13.371,
       'vup': -1.0,
       'vwc1': 11.30646,
       'vwc2': 19.14365}}]
    

    【讨论】:

    • 太棒了,非常感谢 tlentali,它运行良好。将列表转换为元组是我以前从未做过的事情。很高兴你能救我的培根!!
    • 嗨@MarkMorris,如果这个或任何答案已经解决了您的问题,请考虑通过点击复选标记进行投票和accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。很高兴看到它可以帮助您并节省您的培根^^!
    • 不用担心@tlentali,虽然是 Stack Overflow 的常客,但非常业余。感谢您的提示:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 2020-01-03
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多