Развертывание списка из нескольких столбцов в пандах

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

У меня есть такой json:

[{'Id': 1,
  'Design': ["09",
   '10',
   '13'
  ],
  'Research': ['Eng',
   'Math']
  }]

Плюс другие столбцы, не входящие в список. Это повторяется для 500 идентификаторов.

Мне нужно разбить столбцы списка. конечным результатом должен быть файл Excel, мне все равно, выполняется ли взрыв непосредственно в json или в pandas.

Уже пробовал:

    def lenx(x):
        return len(x) if isinstance(x,(list, tuple, np.ndarray, pd.Series)) else 1

    def cell_size_equalize2(row, cols='', fill_mode='internal', fill_value=''):
        jcols = [j for j,v in enumerate(row.index) if v in cols]
        if len(jcols)<1:
            jcols = range(len(row.index))
        Ls = [lenx(x) for x in row.values]
        if not Ls[:-1]==Ls[1:]:
            vals = [v if isinstance(v,list) else [v] for v in row.values]
            if fill_mode=='external':
                vals = [[e] + [fill_value]*(max(Ls)-1) if (not j in jcols) and (isinstance(row.values[j],list))
                        else e + [fill_value]*(max(Ls)-lenx(e))
                        for j,e in enumerate(vals)]
            elif fill_mode == 'internal':
                vals = [[e]+[e]*(max(Ls)-1) if (not j in jcols) and (isinstance(row.values[j],list))
                        else e+[e[-1]]*(max(Ls)-lenx(e)) 
                        for j,e in enumerate(vals)]
            else:
                vals = [e[0:min(Ls)] for e in vals]
            row = pd.Series(vals,index=row.index.tolist())
        return row

Приводит к ошибке индекса

df.explode(['B', 'C', 'D', 'E']).reset_index(drop=True)

Столбцы должны иметь одинаковую длину

df1 = pd.concat([df[x].explode().to_frame()
                      .assign(g=lambda x: x.groupby(level=0).cumcount())
                      .set_index('g', append=True) 
                for x in cols_to_explode], axis=1)

Каким-то образом он создает много строк, я думаю, он просто разрывает столбец за другим, и это приводит к ошибке памяти.

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

Id      Design     Research
1         09          Eng
1         10          Math
1         13  
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать json_normalize и дедупликацию-взрыв (как представлено здесь):

tmp = pd.json_normalize(json)

def explode_dedup(s):
    s = s.explode()
    return s.set_axis(
        pd.MultiIndex.from_arrays([s.index, s.groupby(level=0).cumcount()])
    )

ids = ['Id']
cols = tmp.columns.difference(ids)

out = (tmp[ids]
       .join(pd.concat({c: explode_dedup(tmp[c])
                        for c in cols}, axis=1)
               .droplevel(-1)
            )[tmp.columns]
      )

Примечание. если вы знаете, что столбцы должны взорваться, вы можете альтернативно использовать:

cols = ['Design', 'Research']
ids = tmp.columns.difference(cols)

Выход:

   Id Design Research
0   1     09      Eng
0   1     10     Math
0   1     13      NaN
import pandas as pd
from pandas.io.json._normalize import json_normalize
import numpy as np

data = [
    {
        'Id': 1,
        'Design': ["09", "10", "13"],
        'Research': ['Eng', 'Math']
    }
]

# Convert JSON to DataFrame
#df = pd.DataFrame(data)
df = json_normalize(data)

df['Research'] = df['Research'].transform(
    lambda x: x + [np.nan] * (len(df['Design'].iloc[0]) - len(x))
)
df = df.explode(['Design','Research'],ignore_index = True)
print(df)
"""
   Id Design Research
0   1     09      Eng
1   1     10     Math
2   1     13      NaN
"""

метод 2:

import pandas as pd
from pandas.io.json._normalize import json_normalize
import numpy as np

data = [
    {
        'Id': 1,
        'Design': ["09", "10", "13"],
        'Research': ['Eng', 'Math']
    }
]

# Convert JSON to DataFrame
#df = pd.DataFrame(data)

df = json_normalize(data)

df_exploded1 = df.explode('Design',ignore_index =True).assign(
Research = lambda x : pd.Series(df['Research'].explode().values)
            .reindex(x.index).fillna(np.nan)    
)
print(df_exploded1)

'''
   Id Design Research
0   1     09      Eng
1   1     10     Math
2   1     13      NaN

'''

Другие вопросы по теме