Как можно нормализовать метаданные с помощью функции json_normalize - PullRequest
0 голосов
/ 28 мая 2020

У меня есть вложенный json, и я хотел бы преобразовать его в pandas фрейм данных с помощью функции json_normalize.

JSON

json_input = [{'measurements': [{'value': 111, 'timestamp': 1},
                                {'value': 222, 'timestamp': 2}],
               'sensor': {'name': 'testsensor',
                          'id': 1}},
              {'measurements': [{'value': 333, 'timestamp': 1},
                                {'value': 444, 'timestamp': 2}],
               'sensor': None},
              ]

Нормализация

df = pd.json_normalize(json_input, record_path=['measurements'],
                                   meta=['sensor'])

Метаданные не нормализуются в выводе приведенного выше кода:

|   | value | timestamp | sensor                          |
|---|-------|-----------|---------------------------------|
| 0 | 111   | 1         | {'name': 'testsensor', 'id': 1} |
| 1 | 222   | 2         | {'name': 'testsensor', 'id': 1} |
| 2 | 111   | 1         | None                            |
| 3 | 222   | 2         | None                            |

Есть ли возможность получить желаемый результат:

|   | value | timestamp | sensor.name  | sensor.id |
|---|-------|-----------|--------------|-----------|
| 0 | 111   | 1         | 'testsensor' | 1         |
| 1 | 222   | 2         | 'testsensor' | 1         |
| 2 | 111   | 1         | None         | None      |
| 3 | 222   | 2         | None         | None      |

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Создайте DataFrame с помощью конструктора с заменой пустых списков на пустые словари и соедините вместе concat:

df = pd.json_normalize(json_input, record_path=['measurements'],
                                   meta=['sensor'])

#pandas 1.0.1
df1 = pd.DataFrame([{} if x == [] else x for x in df.pop('sensor')]).add_prefix("sensor.")
#pandas 1.0.3
df1 = pd.DataFrame([{} if x == None else x for x in df.pop('sensor')]).add_prefix("sensor.")

df = pd.concat([df, df1], axis=1)
print (df)
   value  timestamp sensor.name  sensor.id
0    111          1  testsensor        1.0
1    222          2  testsensor        1.0
2    333          1         NaN        NaN
3    444          2         NaN        NaN
0 голосов
/ 28 мая 2020

Это будет делать-> df['sensor'].apply(pd.Series).add_prefix("sensor.")]

df = pd.json_normalize(json_input, record_path=['measurements'],
                                   meta=['sensor'])
df = pd.concat([df, df['sensor'].apply(pd.Series).add_prefix("sensor.")], axis=1)
df.drop('sensor', inplace=True, axis=1)
df

    value   timestamp   sensor.name sensor.id
0   111     1           testsensor  1.0
1   222     2           testsensor  1.0
2   333     1           NaN         NaN
3   444     2           NaN         NaN

Как упоминал джезраэль. .apply(pd.series) медленный, вы можете использовать это:

pd.DataFrame([i if i!=None else {} for i in df['sensor'].tolist()]

df = pd.json_normalize(json_input, record_path=['measurements'],
                                   meta=['sensor'])
df = pd.concat([df, pd.DataFrame([i if i!=None else {} for i in df['sensor'].tolist()]
).add_prefix("sensor")], axis=1)
df.drop('sensor', inplace=True, axis=1)
df
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...