【问题标题】:Flattening nested JSON included embedded array in Python using Pandas使用 Pandas 在 Python 中展平嵌套的 JSON 包含的嵌入式数组
【发布时间】:2017-06-19 14:38:04
【问题描述】:

我有一个来自 mongoexport 的 JSON 数组,其中包含来自 Beddit sleeptracker 的数据。下面是截断文档之一的示例(删除了一些不需要的细节)。

    {
        "user" : "xxx",
        "provider" : "beddit",
        "date" : ISODate("2016-11-30T23:00:00.000Z"),
        "data" : [ 
            {
                "end_timestamp" : 1480570804.26226,
                "properties" : {
                    "sleep_efficiency" : 0.8772404,
                    "resting_heart_rate" : 67.67578,
                    "short_term_resting_heart_rate" : 61.36963,
                    "activity_index" : 50.51958,
                    "average_respiration_rate" : 16.25667,
                    "total_sleep_score" : 64,
                },
                "date" : "2016-12-01",
                "session_range_start" : 1480545636.55059,
                "start_timestamp" : 1480545636.55059,
                "session_range_end" : 1480570804.26226,
                "tags" : [ 
                    "not_enough_sleep", 
                    "long_sleep_latency"
                ],
                "updated" : 1480570805.25201
            }
        ],
        "__v" : 0
    }

thisthis 等几个相关问题似乎不适用于上述数据结构。正如其他相关问题中所建议的那样,出于性能原因,我试图避免循环遍历每一行(完整数据集约为 150MB)。我将如何使用 json_normalize 展平 "data"-key,以便每个 key 都位于顶层?我更喜欢一个 DataFrame,例如total_sleep_score 是一列。

非常感谢任何帮助!尽管我知道如何使用 JavaScript 来“准备”数据,但我希望能够理解并使用 Python 来完成。

编辑(请求评论以显示首选结构):

{
    "user" : "xxx",
    "provider" : "beddit",
    "date" : ISODate("2016-11-30T23:00:00.000Z"),
    "end_timestamp" : 1480570804.26226,
    "properties.sleep_efficiency" : 0.8772404,
    "properties.resting_heart_rate" : 67.67578,
    "properties.short_term_resting_heart_rate" : 61.36963,
    "properties.activity_index" : 50.51958,
    "properties.average_respiration_rate" : 16.25667,
    "properties.total_sleep_score" : 64,
    "date" : "2016-12-01",
    "session_range_start" : 1480545636.55059,
    "start_timestamp" : 1480545636.55059,
    "session_range_end" : 1480570804.26226,
    "updated" : 1480570805.25201,
    "__v" : 0
}

“属性”附加不是必需的,但会很好。

【问题讨论】:

  • 你能提供一个数据应该是什么样子的例子吗?
  • 刚刚编辑了原帖。
  • 如果此 JSON-Object 的格式始终相同,如果您不想循环访问该对象,则可以简单地将 JSON 转换为字符串并操作该字符串。但我不确定这是否会带来更好的性能。
  • “属性”中的参数并不总是相同的。在某些夜晚,某些参数无法计算,因此从通过 API 接收的数据中省略了这些参数。
  • 那么我看不到在不以任何方式迭代的情况下转换 json 的可能性。

标签: python json pandas dataframe


【解决方案1】:

虽然没有明确提出我的要求,但到目前为止,以下内容对我有用:

第一步

在原始数据集(不在 Pandas DataFrame 内)上使用 json_normalize 规范化 data 记录并为 data 添加前缀。

beddit_data = pd.io.json.json_normalize(beddit, record_path='data', record_prefix='data.', meta='_id')

第 2 步

properties 记录是一个带有 dicts 的 Series,因此可以使用 .apply(pd.Series)“格式化”这些记录

beddit_data_properties = beddit_data['data.properties'].apply(pd.Series)

第三步

最后一步是合并两个 DataFrame。在第 1 步中,我保留了“meta=_id”,以便 DataFrame 可以与 Bedit 的原始 DataFrame 合并。我还没有将它包含在最后一步中,因为我可以花一些时间从目前的结果中获得结果。

beddit_final = pd.concat([beddit_data_properties[:], beddit_data[:]], axis=1)

如果有人有兴趣,我可以在准备好最终的 Jupyter Notebook 时分享它:)

【讨论】:

    【解决方案2】:

    试试这个算法扁平化:-

    def flattenPattern(pattern):
        newPattern = {}
        if type(pattern) is list:
            pattern = pattern[0]
    
        if type(pattern) is not str:
            for key, value in pattern.items():
                if type(value) in (list, dict):
                    returnedData = flattenPattern(value)
                    for i,j in returnedData.items():
                            if key == "data":
                                newPattern[i] = j
                            else:
                                newPattern[key + "." + i] = j
                else:
                    newPattern[key] = value
    
    
        return newPattern 
    
    
     print(flattenPattern(dictFromJson))
    
    
    OutPut:-
    {  
      'session_range_start':1480545636.55059,
      'start_timestamp':1480545636.55059,
      'properties.average_respiration_rate':16.25667,
      'session_range_end':1480570804.26226,
      'properties.resting_heart_rate':67.67578,
      'properties.short_term_resting_heart_rate':61.36963,
      'updated':1480570805.25201,
      'properties.total_sleep_score':64,
      'properties.activity_index':50.51958,
      '__v':0,
      'user':'xxx',
      'provider':'beddit',
      'date':'2016-12-01',
      'properties.sleep_efficiency':0.8772404,
      'end_timestamp':1480570804.26226
    }
    

    【讨论】:

    • 这会给我一个 'AttributeError: 'unicode' object has no attribute 'items'' ' 错误。
    • @martwetzels,我认为您将 json 直接传递给此函数,首先将 json 加载到变量,例如 x = json.loads(您的 json 字符串)。然后这将起作用。并查看我的变量名 dictFromJson 它指示来自 json 的 dict 对象。
    猜你喜欢
    • 2021-12-31
    • 2021-10-09
    • 2023-03-07
    • 2022-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多