Как создать сложный словарь с вложенным словарем в списке в Pandas DataFrame в потоковых данных

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

Я пытаюсь создать фрейм данных из сложного словаря здесь, но я не могу решить значения для последнего столбца, если бы вы могли, пожалуйста, направить меня, это было бы здорово!

код —

 import pandas as pd
from pandas.io.json import json_normalize

stream= {
    "Outerclass": {
        "Main_ID": "1",
        "SetID": "1041",
        "Version": 2,
        "nestedData": {
            "time": ["5000", "6000", "7000"],
            "values": [{"intValue":1,"value":"intValue"}, {"floatValue":2.5,"value":"floatValue"}, {"stringValue":"abc","value":"stringValue"}]
        }

    } }


s = json_normalize(stream['Outerclass'])
s = s.join(pd.concat([s.pop(x).explode()  for x in ['nestedData.time','nestedData.values']],axis=1))
print(s)
  

Желаемый результат-

 Main_ID SetID   Version nestedData.time nestedData.values
1       1041    2       5000            1
1       1041    2       6000            2.5
1       1041    2       7000            abc
  

Фактический результат —

 Main_ID SetID   Version nestedData.time nestedData.values
1       1041    2       5000            {'intValue': 1, 'value': 'intValue'}
1       1041    2       6000            {'floatValue': 2.5, 'value': 'floatValue'}
1       1041    2       7000            {'stringValue': 'abc', 'value': 'stringValue'}
  

Комментарии:

1. Первый ключ nestedData.values отличается для каждой строки (например 'intValue' , floatValue , stringValue ), поэтому, даже если вы еще раз нормализуете этот json, все они будут отдельными столбцами. Вы хотите по существу игнорировать имя этого ключа и получать связанное значение независимо от того, является ли оно intValue , floatValue , и т. Д.?

2. да, мне нужно игнорировать подтекст первого ключа и хотеть только связанное значение

Ответ №1:

Поскольку вы хотите извлечь некоторые из этих полей на основе пользовательской логики (не обязательно классической нормализации json), что требует игнорирования подтекста первого ключа и, по сути, получения любого значения, связанного с ключом, которого нет value , я бы предложил следующее:

 # Almost same as before
s = pd.json_normalize(stream['Outerclass']) #pandas.io.json.json_normalize is actually deprecated
s = s.join(pd.concat(
           [s.pop(x).explode() for x in ['nestedData.time','nestedData.values']], axis=1)
          ).reset_index(drop=True)

def get_value(d):
    """ Extract value from any key that is not 'value' """
    k = [k for k in d.keys() if k != 'value'][0]
    return d.get(k)

s["Values"] = s["nestedData.values"].apply(get_value) # Or you can just replace it
s
  

Результирующий фрейм данных будет выглядеть следующим образом:

     Main_ID SetID   Version nestedData.time nestedData.values
0   1       1041    2       5000            1
1   1       1041    2       6000            2.5
2   1       1041    2       7000            abc
  

Кроме того, просто чтобы отметить альтернативу, используя только нормализацию json:

 pd.json_normalize(s["nestedData.values"])
  

в результате будет получена таблица с каждым возможным ключом в виде столбца, как ожидалось (но не так, как хотелось бы):

     intValue    value       floatValue  stringValue
0   1.0     intValue    NaN         NaN
1   NaN     floatValue  2.5         NaN
2   NaN     stringValue NaN         abc