【问题标题】:Partly flatten nested JSON objects stored in df column部分展平存储在 df 列中的嵌套 JSON 对象
【发布时间】:2022-01-19 13:45:37
【问题描述】:

我有一个包含 3 列(INSTNREnhedsadresserAPI_response)的数据框,其中第 3 列(API_response strong>) 包含 JSON 对象。我想展平 JSON 对象并将提取的信息存储在同一 df 中的单独列中。我对提取 categoriresultater -> adresse -> idresultater -> adresse -> adgangsadresseid 信息特别感兴趣。

我试过了:

data = json_normalize(data=df['API_response'], record_path='resultater',
                            meta=['kategori'], errors='ignore')

但它只是返回 TypeError: string indices must be integers

data = json_normalize(data=df['API_response']) 给了我一个包含索引列表的列...

如何提取所需信息?

JSON 对象示例:

{
  "kategori": "A",
  "resultater": [
    {
      "adresse": {
        "id": "0a3f50bc-f815-32b8-e044-0003ba298018",
        "vejnavn": "Staldgaardsgade",
        "adresseringsvejnavn": "Staldgaardsgade",
        "husnr": "39A",
        "supplerendebynavn": null,
        "postnr": "7100",
        "postnrnavn": "Vejle",
        "status": 1,
        "virkningstart": "2009-11-24T02:15:25.000Z",
        "virkningslut": null,
        "adgangsadresseid": "0a3f5090-edef-32b8-e044-0003ba298018",
        "etage": "st",
        "dør": "th",
        "href": "https://api.dataforsyningen.dk/adresser/0a3f50bc-f815-32b8-e044-0003ba298018"
      },
      "aktueladresse": {
        "id": "0a3f50bc-f815-32b8-e044-0003ba298018",
        "vejnavn": "Staldgaardsgade",
        "adresseringsvejnavn": "Staldgaardsgade",
        "husnr": "39A",
        "supplerendebynavn": null,
        "postnr": "7100",
        "postnrnavn": "Vejle",
        "status": 1,
        "virkningstart": "2009-11-24T02:15:25.000Z",
        "virkningslut": null,
        "adgangsadresseid": "0a3f5090-edef-32b8-e044-0003ba298018",
        "etage": "st",
        "dør": "th",
        "href": "https://api.dataforsyningen.dk/adresser/0a3f50bc-f815-32b8-e044-0003ba298018"
      },
      "vaskeresultat": {
        "variant": {
          "vejnavn": "Staldgaardsgade",
          "husnr": "39A",
          "etage": "st",
          "dør": "th",
          "supplerendebynavn": null,
          "postnr": "7100",
          "postnrnavn": "Vejle"
        },
        "afstand": 0,
        "forskelle": {
          "vejnavn": 0,
          "husnr": 0,
          "postnr": 0,
          "postnrnavn": 0,
          "etage": 0,
          "dør": 0
        },
        "parsetadresse": {
          "vejnavn": "Staldgaardsgade",
          "husnr": "39A",
          "etage": "st",
          "dør": "th",
          "postnr": "7100",
          "postnrnavn": "Vejle"
        },
        "ukendtetokens": [],
        "anvendtstormodtagerpostnummer": null
      }
    }
  ]
}

包含此 JSON 对象的 API 响应链接:https://api.dataforsyningen.dk/datavask/adresser?betegnelse=Staldgaardsgade%2039A%20st%20th,%207100%20Vejle

编辑 1

我使用数据和 python 脚本创建了 GitHub 存储库:https://github.com/mantasbacys/TREFOR

【问题讨论】:

  • 你能提供一个可重现的例子吗? IE。你如何创建你的df
  • 这只是一个简单的pd.read_excel。我附上了包含文件的 GitHub 存储库链接(帖子的最后一行)。

标签: python json pandas typeerror json-normalize


【解决方案1】:

Series.str.get 可以帮助您从字典列中提取单个元素。

如果API_response 是一列格式为您的示例的字典,您可以使用:

df['kategori'] = df['api_response'].str.get('kategori')
df['id'] = (
    df['api_response']
    .str.get('resultater')  # get resultater object
    .str.get(0)  # get first element in list
    .str.get('adresse')
    .str.get('id')
)
df['adgangsadresseid'] =  = (
    df['api_response']
    .str.get('resultater')  # get resultater object
    .str.get(0)  # get first element in list
    .str.get('adresse')
    .str.get('adgangsadresseid')
)

请注意,如果格式不匹配,这将失败,因此请仔细检查!例如。如果resultater 列表中有多个元素,您可能需要改用Series.explode


编辑:

您的文件显示API_response 列实际上包含保存为字符串 的已解析JSON 字典。这意味着 .str.get 方法不起作用,因为值不是有效的字典。

作为一种快速修复,您应该将字典字符串转换为实际字典首先

def convert(s): 
    """Convert dictionary string to JSON-like format and parse with json module"""
    s = s.replace("'", '"')
    s = s.replace("None", "null")
    return json.loads(s)

df['api_response'] = df.API_response.apply(convert)
# Alternative - UNSAFE! (see https://stackoverflow.com/questions/1832940/why-is-using-eval-a-bad-practice)
# df['api_response'] = df.API_response.apply(eval)

我假设这是因为您首先下载数据,然后将其解析为字典,并在再次加载之前保存在文件中。保存文件时会发生这种到字符串列的转换。

为避免这种与字符串之间的转换,请尝试在单个脚本中解析 JSON 并提取感兴趣的值。

【讨论】:

  • 我在运行代码时得到这个:AttributeError: Can only use .str accessor with string values! 是不是因为.str 方法不能与字典一起使用? API_response 列中的所有单元格的格式与我的示例相同。
  • 哪一行抛出这个错误? .str 可以在不同的object 列上使用,前提是格式正确
  • 我在第 4 行得到它:.str.get('resultater')
  • 查看编辑;也 - 或者,您可以使用 .str[item] 而不是 .str.get(item)
  • 太好了,当我将您的代码行更改为 df['API_response'].str.get('resultater').str[0].str.get('adresse').str.get('id') 时,它在转换为 dict 后就像一个魅力!感谢您抽出宝贵时间提供帮助!
猜你喜欢
  • 2021-10-19
  • 2012-05-29
  • 1970-01-01
  • 2020-03-02
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多