Добавить столбец из pandas DataFrame в глубоко вложенный JSON с указанным c уровнем объекта - PullRequest
0 голосов
/ 02 марта 2020

Предположим, у меня есть DataFrame df, например:

source      tables      columns   data_type   length    RecordCount
src1        table1      col1      INT         4         71
src1        table1      col2      CHAR        2         71
src1        table2      col1      CHAR        2         43
src2        table1      col1      INT         4         21
src2        table1      col2      DATE        3         21

Требуется вывод, похожий на:

{
  "src1": {
    "table1": {
      "Record Count": 71 #missing in my current code output
      "col1": {
        "type": "INT"
        "length": 4
      },
      "col2": {
        "type": "CHAR"
        "length": 2
      }
    },
    "table2": {
      "Record Count": 43 #missing in my current code output
      "col1": {
        "type": "CHAR"
        "length": 2
      }
    }
  },
  "src2": {
    "table1": {
      "Record Count": 21 #missing in my current code output
      "col1": {
        "type": "INT"
        "length": 4
      },
      "col2": {
        "type": "DATE"
        "length": 3
      }
    }
  }
}

Текущий код:

def make_nested(df): 
    f = lambda: defaultdict(f)   
    data = f()  

    for row in df.to_numpy().tolist():
        t = data
        for index, r in enumerate(row[:-4]):
            t = t[r]
            if index == 1:
               t[row[-5]]: {
                  "Record Count": row[-1]
               }
        t[row[-4]] = {
            "type": row[-3],
            "length": row[-2]
        }

    return data

1 Ответ

1 голос
/ 02 марта 2020

Вот еще одно решение - использовать два шага группового метода.

# First, groupby ['source','tables'] to deal with the annoying 'Record Count'
# Need python 3.5+
# Otherwise, another method to merge two dicts should be used 
df_new=df.groupby(['source','tables']).apply(lambda x: {**{'Record Count':x.iloc[0,-1]}, **{x.iloc[i,-4]: {'type':x.iloc[i,-3],'length':x.iloc[i,-2]} for i in range(len(x))}}).reset_index()

См. Слияние диктов

После первого шага df_new выглядит

    source  tables  0
0   src1    table1  {'Record Count': 71, 'col1': {'type': 'INT', 'length': 4}, 'col2': {'type': 'CHAR', 'length': 2}}
1   src1    table2  {'Record Count': 43, 'col1': {'type': 'CHAR', 'length': 2}}
2   src2    table1  {'Record Count': 21, 'col1': {'type': 'INT', 'length': 4}, 'col2': {'type': 'DATE', 'length': 3}}
# Second groupby
df_final = df_new.groupby('source').apply(lambda x: {x.iloc[i,-2]: x.iloc[i,-1] for i in range(len(x))})
output = df_final.to_json()

output - это кодированный строковый тип файла json. Чтобы получить версию с отступом

import json
temp = json.loads(output)
with open('somefile','w') as f:
    json.dump(temp,f,indent=4)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...