Защитите вложенный объект от сглаживания при использовании pandas.json_normalize
В 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"
}
}
]
}
'''
Это отдельная запись JSON из ответа API. Здесь есть только один элемент в списке верхнего уровня, но их может быть больше, каждый из которых имеет ту же структуру, что и показанный здесь. Я хотел бы импортировать это в DataFrame без столбцов, содержащих структурированный элемент, а именно, я хочу сгладить / нормализовать их все. Ну ... почти все.
json_normalize()
отлично справляется с этим:
import pandas as pd
data = json.loads(res)['results']
df = pd.DataFrame(pd.json_normalize(data))
А вот столбцы DataFrame:
>>> print(f.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')
Есть ли способ сделать это правильно?
1 ответ
Учитывать
max_level=0
. За<strong>
<tcode id="6180976"></tcode></strong>документы :
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')