使用 json_normalize 与带有单键的无关字典层?

问题描述 投票:0回答:1

我有自动识别系统(AIS)数据作为 pandas 数据框中的嵌套字典。这是一个例子:

dfAIS
Out[18]:
                                                  Message  ...                                           MetaData
0       {'ShipStaticData': {'AisVersion': 1, 'CallSign...  ...  {'MMSI': 255814000, 'MMSI_String': 255814000, ...
1       {'MultiSlotBinaryMessage': {'ApplicationID': {...  ...  {'MMSI': 2276003, 'MMSI_String': 2276003, 'Shi...
2       {'StandardClassBPositionReport': {'AssignedMod...  ...  {'MMSI': 503760500, 'MMSI_String': 503760500, ...
3       {'PositionReport': {'Cog': 25.2, 'Communicatio...  ...  {'MMSI': 211648000, 'MMSI_String': 211648000, ...
4       {'StaticDataReport': {'MessageID': 24, 'PartNu...  ...  {'MMSI': 338467989, 'MMSI_String': 338467989, ...
                                                  ...  ...                                                ...
139625  {'PositionReport': {'Cog': 360, 'Communication...  ...  {'MMSI': 244730300, 'MMSI_String': 244730300, ...
139626  {'PositionReport': {'Cog': 231.5, 'Communicati...  ...  {'MMSI': 219025528, 'MMSI_String': 219025528, ...
139627  {'PositionReport': {'Cog': 360, 'Communication...  ...  {'MMSI': 273252100, 'MMSI_String': 273252100, ...
139628                             {'UnknownMessage': {}}  ...  {'MMSI': 244730043, 'MMSI_String': 244730043, ...
139629  {'ShipStaticData': {'AisVersion': 1, 'CallSign...  ...  {'MMSI': 211666470, 'MMSI_String': 211666470, ...

[139630 rows x 3 columns]

核心数据位于“消息”栏。其中每个元素都是一个只有 1 个键和 1 个值的字典。如上所示,一个键可能是“ShipStaticData”、“MultiSlotBinaryMessage”等,我们可以将其视为消息类型。我们将这个字典称为一级字典。

一级字典是一个无关的映射层,因为所需的数据驻留在相应的值中,而相应的值本身就是一个完整的字典。我们将后者称为二级词典。如上所示,二级字典中的字段可以是“AisVersion”、“ApplicationID”、“Cog”等。here指定有效字段。

我不需要 1 级字典的键,因为 2 级字典包含一个 MessageID 字段,该字段更明确地映射到消息类型。此外,数据框

dfAIS
还有一个上面未显示的MessageType列,它包含与1级字典中唯一键相同的标签。

我一直在自学数据帧操作,使用 apply 从 2 级字典中提取 MessageID。我还发现 json_normalize 是一个不错的选择。不幸的是,在嵌套字典中,它要求公共字段的分层路径具有相同的路径组件。我无法将它用于上述场景,因为

Message.ShipStaticData.MessageID
Message.MultiSlotBinaryMessage.MessageID
是不同的路径。在这两条路径中,3 个路径组件中的第 2 个是我希望不存在的无关映射层。

如何取消嵌套嵌套字典以便可以访问 MessageID 字段?

我尝试使用

pandas.DataFrame.apply
将字典方法
items()
应用于
dfAIS
Message
的元素。它产生一系列嵌套元组并且 无关的消息类型键仍然存在:

df = dfAIS.Message.apply(dict.items)

0         ((ShipStaticData, {'AisVersion': 1, 'CallSign'...
1         ((MultiSlotBinaryMessage, {'ApplicationID': {'...
2         ((StandardClassBPositionReport, {'AssignedMode...
3         ((PositionReport, {'Cog': 25.2, 'Communication...
4         ((StaticDataReport, {'MessageID': 24, 'PartNum...
                       
139625    ((PositionReport, {'Cog': 360, 'CommunicationS...
139626    ((PositionReport, {'Cog': 231.5, 'Communicatio...
139627    ((PositionReport, {'Cog': 360, 'CommunicationS...
139628                               ((UnknownMessage, {}))
139629    ((ShipStaticData, {'AisVersion': 1, 'CallSign'...
Name: Message, Length: 139630, dtype: object

P.S. 我也在纠结如何引用“ShipStaticData”、“MultiSlotBinaryMessage”等标签。它们是 1 级字典的键。谈论 1 级键所采用的“值”本来很方便,但“值”已经指的是键映射到的事物。我们可以非常仔细地说,后者是与键关联的值,或者是键的值,但这仍然会造成混淆。是否有更清晰(且简洁)的方式来引用“ShipStaticData”、“MultiSlotBinaryMessage”等? 人们经常忘记 JSON 只是 Python 中的普通数据结构,并且他们可以在初始化数据帧之前进行操作。并非所有事情都需要由 pandas 处理。

python json pandas dictionary data-ingestion
1个回答
0
投票

with open("data.json") as fp: data = json.load(fp) messages = [ value for message in data["Message"] for _, value in message.items() ] df = pd.DataFrame(messages)

© www.soinside.com 2019 - 2024. All rights reserved.