展平嵌套 json 使每个项目一行

Flattening nested json to have one row per item

我有一个嵌套的 json,我正试图将其展平:

[
  {
    "name": "table1",
    "count": 123,
    "columns": {
      "col1": "string",
      "col2": "string"
    },
    "partitions": 2
  },
  {
    "name": "table2",
    "count": 234,
    "columns": {
      "col3": "int",
      "col4": "string",
      "col5": "int"
    },
    "partitions": 4
  }
]

我正在尝试将其扁平化为如下所示:

name     count   col_name     col_type   partitions
table1    123      col1        string      2
table1    123      col2        string      2
table2    234      col3        int         4
table2    234      col4        string      4
table2    234      col5        int         4

正在将 json 读入 pandas 数据帧。

with open("file.json") as datafile:
    data = json.load(datafile)
dataframe = pd.DataFrame(data)

pd.json_normalize 不起作用,因为我不想创建太多列。 相反,我正在尝试创建更多行。 有人可以指导我如何在 python 或使用 pandas 中最好地实现这一目标吗?

感谢任何帮助。 谢谢。

您可以使用 wide_to_long:

df = pd.json_normalize(data)
cols = [c for c in df.columns if not c.startswith('columns')]

out = (pd.wide_to_long(df, stubnames='columns', i=cols, j='col_name', 
                       sep='.', suffix='col\d+')
         .rename(columns={'columns': 'col_type'})
         .query('col_type.notna()').reset_index())
print(out)

# Output
     name  count  partitions col_name col_type
0  table1    123           2     col1   string
1  table1    123           2     col2   string
2  table2    234           4     col3      int
3  table2    234           4     col4   string
4  table2    234           4     col5      int

这是直接的解决方案,您从相应的键中形成一堆字典,然后从中创建一个数据框。

import json
import pandas as pd
with open("abc.json") as datafile:
    data = json.load(datafile)
print(data)
d = [{'name': x['name'],'count':x['count'],'colname':k,'coltype':x['columns'][k], 'partitions':x['partitions']} for x in data for k in x['columns'].keys()]
df = pd.DataFrame.from_dict(d)
print(df)

输出

[{'name': 'table1', 'count': 123, 'columns': {'col1': 'string', 'col2': 'string'}, 'partitions': 2}, {'name': 'table2', 'count': 234, 'columns': {'col3': 'int', 'col4': 'string', 'col5': 'int'}, 'partitions': 4}]
     name  count colname coltype  partitions
0  table1    123    col1  string           2
1  table1    123    col2  string           2
2  table2    234    col3     int           4
3  table2    234    col4  string           4
4  table2    234    col5     int           4