【问题标题】:Pandas read nested json熊猫读取嵌套的 json
【发布时间】:2017-03-28 02:19:13
【问题描述】:

我很好奇如何使用 pandas 读取以下结构的嵌套 json:

{
    "number": "",
    "date": "01.10.2016",
    "name": "R 3932",
    "locations": [
        {
            "depTimeDiffMin": "0",
            "name": "Spital am Pyhrn Bahnhof",
            "arrTime": "",
            "depTime": "06:32",
            "platform": "2",
            "stationIdx": "0",
            "arrTimeDiffMin": "",
            "track": "R 3932"
        },
        {
            "depTimeDiffMin": "0",
            "name": "Windischgarsten Bahnhof",
            "arrTime": "06:37",
            "depTime": "06:40",
            "platform": "2",
            "stationIdx": "1",
            "arrTimeDiffMin": "1",
            "track": ""
        },
        {
            "depTimeDiffMin": "",
            "name": "Linz/Donau Hbf",
            "arrTime": "08:24",
            "depTime": "",
            "platform": "1A-B",
            "stationIdx": "22",
            "arrTimeDiffMin": "1",
            "track": ""
        }
    ]
}

这里将数组保存为 json。我宁愿把它展开成列。

pd.read_json("/myJson.json", orient='records')

编辑

感谢您的第一个答案。 我应该完善我的问题: 数组中嵌套属性的展平不是强制性的。 只需 [A, B, C] 连接 df.locations['name'] 就可以了。

我的文件包含多个 JSON 对象(每行 1 个)我想保留数字、日期、名称和位置列。但是,我需要加入这些位置。

allLocations = ""
isFirst = True
for location in result.locations:
    if isFirst:
        isFirst = False
        allLocations = location['name']
    else:
        allLocations += "; " + location['name']
allLocations

我这里的方法似乎效率不高/熊猫风格。

【问题讨论】:

  • 最简单的方法,你可以查看我的回答here

标签: python json parsing pandas


【解决方案1】:

你可以使用json_normalize:

import json

with open('myJson.json') as data_file:    
    data = json.load(data_file)  

df = pd.json_normalize(data, 'locations', ['date', 'number', 'name'], 
                    record_prefix='locations_')
print (df)
  locations_arrTime locations_arrTimeDiffMin locations_depTime  \
0                                                        06:32   
1             06:37                        1             06:40   
2             08:24                        1                     

  locations_depTimeDiffMin           locations_name locations_platform  \
0                        0  Spital am Pyhrn Bahnhof                  2   
1                        0  Windischgarsten Bahnhof                  2   
2                                    Linz/Donau Hbf               1A-B   

  locations_stationIdx locations_track number    name        date  
0                    0          R 3932         R 3932  01.10.2016  
1                    1                         R 3932  01.10.2016  
2                   22                         R 3932  01.10.2016 

编辑:

您可以将read_jsonDataFrame 构造函数解析name 一起使用,最后将groupby 与apply join 一起使用:

df = pd.read_json("myJson.json")
df.locations = pd.DataFrame(df.locations.values.tolist())['name']
df = df.groupby(['date','name','number'])['locations'].apply(','.join).reset_index()
print (df)
        date    name number                                          locations
0 2016-01-10  R 3932         Spital am Pyhrn Bahnhof,Windischgarsten Bahnho... 

【讨论】:

  • 而 json 将是原始文件?还是文件路径?
  • 在文档中它是 Unserialized JSON objects,但我用 dict 测试它。
  • 我明白了。谢谢。哪些列需要进入 ['date', 'number', 'name'] 数组?这对我来说仍然有点不清楚。对我来说,连接所有位置的名称并保留该列就足够了。
  • 我认为这是未嵌套在 [] 中的第一级数据。在locations是嵌套数据{},所以是第二个参数。
  • @jezrael 感谢您的解决方案。我正在解决类似的问题,您的解决方案确实有效。但是,在此示例中,它会删除列“位置”缺失值的行。关于如何在不删除位置列的任何缺失值的行的情况下读取数据的任何建议?
【解决方案2】:

pandas.json_normalize 的一种可能替代方法是通过仅从嵌套字典中提取选定的键和值来构建您自己的数据框。这样做的主要原因是因为 json_normalize 对于非常大的 json 文件变得很慢(并且可能并不总是产生你想要的输出)。

因此,这是使用glom 扁平化熊猫中嵌套字典的另一种方法。目的是从嵌套字典中提取选定的键和值,并将它们保存在 pandas 数据框的单独列中(:

这是一步一步的指南:https://medium.com/@enrico.alemani/flatten-nested-dictionaries-in-pandas-using-glom-7948345c88f5

import pandas as pd
from glom import glom
from ast import literal_eval


target = {
    "number": "",
    "date": "01.10.2016",
    "name": "R 3932",
    "locations":
        {
            "depTimeDiffMin": "0",
            "name": "Spital am Pyhrn Bahnhof",
            "arrTime": "",
            "depTime": "06:32",
            "platform": "2",
            "stationIdx": "0",
            "arrTimeDiffMin": "",
            "track": "R 3932"
        }
}   



# Import data
df = pd.DataFrame([str(target)], columns=['target'])

# Extract id keys and save value into a separate pandas column
df['id'] = df['target'].apply(lambda row: glom(literal_eval(row), 'locations.name'))

【讨论】:

    猜你喜欢
    • 2018-05-05
    • 2022-07-06
    • 1970-01-01
    • 2014-08-13
    • 2022-07-12
    • 2015-10-11
    • 2020-12-28
    • 1970-01-01
    相关资源
    最近更新 更多