簡體   English   中英

使用 Pandas 在 Python 中展平嵌套的 JSON 包含的嵌入式數組

[英]Flattening nested JSON included embedded array in Python using Pandas

我有一個來自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
    }

這樣這樣的幾個相關問題似乎不適用於上面的數據結構。 正如其他相關問題中所建議的那樣,出於性能原因,我試圖避免遍歷每一行(完整數據集約為 150MB)。 我將如何使用 json_normalize 將“data” -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
}

“屬性”附加不是必需的,但會很好。

試試這個算法扁平化:-

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步

使用原始數據集(不在 Pandas DataFrame 內)上的 json_normalize 規范化數據記錄並為數據添加前綴

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

第2步

屬性記錄是一個帶有字典的系列,因此可以使用 .apply(pd.Series) '格式化'

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

第 3 步

最后一步是合並兩個 DataFrame。 在第 1 步中,我保留了 'meta=_id',以便 DataFrame 可以與來自 Beedit 的原始 DataFrame 合並。 我還沒有將它包含在最后一步中,因為我可以花一些時間在到目前為止的結果上。

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

如果有人感興趣,我可以在准備好后分享最終的 Jupyter Notebook :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM