使用Pandas在Python中展平嵌套JSON包含嵌入式数组

时间:2017-02-02 13:36:52

标签: python json pandas dataframe

我有一个来自 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展开"数据" -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
}

'属性'追加是没有必要但会很好。

2 个答案:

答案 0 :(得分:0)

尝试这个算法来展平: -

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
}

答案 1 :(得分:0)

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

第1步

使用原始数据集上的json_normalize(不在Pandas DataFrame中)标准化数据记录,并为数据添加前缀。

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

第2步

属性记录是带有dicts的系列,因此可以使用.apply(pd.Series)“格式化”

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

第3步

最后一步是合并两个DataFrame。在第1步中,我保留了'meta = _id',以便DataFrame可以与Bedit的原始DataFrame合并。我还没有把它包括在最后一步中,因为到目前为止,我可以花一些时间来研究结果。

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

如果有人有兴趣,我可以在准备好后分享最终的Jupyter笔记本:)