0

在 pandas >= 1.1.4 / Python 3 中,我想在使用json_normalize()时保护嵌套元素不被展平。

我无法在文档中弄清楚这样的事情。

实际示例

这是一个具体的例子来弄清楚主要思想:

res='''
    {
      "results": [
        {
          "geometry": {
            "type": "Polygon",
            "crs": 4326,
            "coordinates": 
              [[
                  [6.0, 49.0],
                  [6.0, 40.0],
                  [7.0, 40.0],
                  [7.0, 49.0],
                  [6.0, 49.0]
              ]]
          },
          "attribute": "layer.metadata",
          "bbox": [6, 40, 7, 49],
          "featureName": "Coniferous_Trees",
          "layerName": "State_Forests",
          "type": "Feature",
          "id": "17",
          "properties": {
            "resolution": "100",
            "Year": "2020",
            "label": "Coniferous"
          }
        }
      ]
    }
'''

这是来自 API 响应的单个 JSON 记录。在这里,顶级列表中只有一个元素,但可能还有更多,每个元素都遵循与此处所示相同的结构。我想将它导入到没有包含结构化元素的列的DataFrame中,即我想将它们全部展平/规范化。嗯,……几乎所有。json_normalize()在这方面做得非常出色:

import pandas as pd

data = json.loads(res)['results']
df = pd.DataFrame(pd.json_normalize(data))

以下是 DataFrame 的列:

>>> print(df.columns)
Index(['attribute', 'bbox', 'featureName', 'layerName', 'type', 'id',
       'geometry.type', 'geometry.crs', 'geometry.coordinates', # <-- the geometry has been flattened
       'properties.resolution', 'properties.Year', 'properties.label'],
      dtype='object')

通缉行为

但是我需要,让我们说,“保护”geometry输入 JSON 响应中的对象不被展平,以便我最终得到这些列:

# e.g. something like this:
df = pd.DataFrame(pd.json_normalize(data, protect="results.geometry"))
# or this if there isn't two objects with the same name:
df = pd.DataFrame(pd.json_normalize(data, protect="geometry"))

这将导致:

>>> print(df.columns)

Index(['attribute', 'bbox', 'featureName', 'layerName', 'type', 'id',
       'geometry', 'properties.resolution', # <-- the geometry element has been protected!
       'properties.Year', 'properties.label'],
      dtype='object')

有没有办法正确地做到这一点?

4

1 回答 1

0

考虑max_level=0。每个pandas.json_normalize文档

max_level:int,默认无
最大级别数(字典深度)进行规范化。如果没有,则标准化所有级别。

data = json.loads(response)["results"]
df = pd.DataFrame(pd.json_normalize(data, max_level=0))

print(df.T)
#                                                              0
# geometry     {'type': 'Polygon', 'crs': 4326, 'coordinates'...
# attribute                                       layer.metadata
# bbox                                            [6, 40, 7, 49]
# featureName                                   Coniferous_Trees
# layerName                                        State_Forests
# type                                                   Feature
# id                                                          17
# properties   {'resolution': '100', 'Year': '2020', 'label':...

print(df.columns)
# Index(['geometry', 'attribute', 'bbox', 'featureName', 'layerName', 'type', 'id', 
#        'properties'], dtype='object')

并且由于所有嵌套对象都未标准化,因此使用数据整理来展开所需的列,例如properties

df = (
       df.drop(['properties'], axis="columns")
         .join(df["properties"].dropna().apply(pd.Series))
     )


print(df.T)
#                                                              0
# geometry     {'type': 'Polygon', 'crs': 4326, 'coordinates'...
# attribute                                       layer.metadata
# bbox                                            [6, 40, 7, 49]
# featureName                                   Coniferous_Trees
# layerName                                        State_Forests
# type                                                   Feature
# id                                                          17
# resolution                                                 100
# Year                                                      2020
# label                                               Coniferous

print(df.columns)
# Index(['geometry', 'attribute', 'bbox', 'featureName', 'layerName', 'type', 'id',
#        'resolution', 'Year', 'label'], dtype='object')
于 2021-03-16T19:16:08.177 回答