Обратное преобразование строк и столбцов в Python

#python #pandas #numpy

#питон #панды #тупица

Вопрос:

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

Данные

 stat1 stat2 id q122con q122av q122con q122av q222con q222av q222con q222av  50 1000 aa 40 10 900 100 50 0 1000 0   100 2000 bb 50 50 1500 500 75 25 1900 100          

Желанный

 stat1 stat2 id date con av con av  50 1000 aa q122 40 10 900 100  50 1000 aa q222 50 0 1000 0  100 2000 bb q122 50 50 1500 500  100 2000 bb q222 75 25 1900 100      

Делающий

 df.pivot(index="id", columns="date", values=["con", "av"])  

Однако я не получаю полные столбцы в своем наборе данных. Любое предложение приветствуется.

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

1. Смотреть pd.wide_to_long в.

Ответ №1:

Какая-то длинная строчка мимо wide_to_long

 pd.wide_to_long(df.set_index(['stat1','stat2','id']).stack().groupby(level=[0,1,2,3]).agg(list).apply(pd.Series).unstack().stack(level=0).reset_index(),  stubnames = ['q122','q222'], i = ['stat1','stat2','id','level_3'],j = 'date',suffix='\w ').stack().unstack(level=[-3,-2]) Out[140]:  level_3 0 1  date av con av con stat1 stat2 id  50 1000 aa q122 10 40 100 900  q222 0 50 0 1000 100 2000 bb q122 50 50 500 1500  q222 25 75 100 1900  

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

1. привет @BENY также, что означает .stack().unstack(уровень=[-3,-2])? это означает удаление определенных столбцов? Также, что такое группа(уровень=[0,1,2,3])? означает ли это количество столбцов? (av, con, av con?) Спасибо

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

Ответ №2:

Многие из ваших проблем здесь связаны с дублированием имен столбцов:

 import pandas as pd  # Duplicating input dataframe with clipboard and remove dot numbers assign for duplicate column headers df = pd.read_clipboard() df.columns = df.columns.str.split('.').str[0]   # Set index to move first three columns into index df = df.set_index(['stat1','stat2','id'])  # Use groupby and cumcount to get order of duplicate column headers cols = df.groupby(df.columns, axis=1).cumcount().rename('No').reset_index()  # Use str.extract to split "dates" from av and con with regex cols = cols['index'].str.extract('(qd{3})(.*)').join(cols).drop('index', axis=1)  # Create a new multiIndex column header df.columns = pd.MultiIndex.from_frame(cols, names=['date','av','con'])  # Reshape dataframe by stacking the outer most column header to the dataframe index # And moved those columns from the index back into the dataframe with reset_index df_out = df.stack(0).reset_index()  # Flatten headers back to one level df_out.columns = [f'{i}_{j}' if j else f'{i}' for i, j in df_out.columns]  # And print print(df_out)  

Выход:

 stat1 stat2 id date av av_1 con con_1 0 50 1000 aa q122 10 100 40 900 1 50 1000 aa q222 0 0 50 1000 2 100 2000 bb q122 50 500 50 1500 3 100 2000 bb q222 25 100 75 1900  

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

1. Я получаю ошибку значения со второй строкой кода: Ошибка значения: Длина переданных значений равна 8, индекс подразумевает 2. @Scott Boston — Я буду исследовать

Ответ №3:

Это не так красиво, как другие решения, но это работает:

 out = df.set_index(['stat1','stat2','id']).stack() idx = pd.DataFrame(out.index.tolist()) count = idx.groupby(idx.columns.tolist()).cumcount().tolist() idx = (idx.iloc[:,:-1]  .merge(idx.iloc[:,-1].str.extract('(qd{3})(.*)'), left_index=True, right_index=True)) out.index = pd.MultiIndex.from_frame(idx, names=['stat1','stat2','id','date','val']) out = (out  .to_frame()  .assign(count=count)  .groupby(['count','val','stat1','stat2','id','date'])  .first()  .unstack(level=[0,1])  .droplevel([0,1], axis=1)  .reset_index()  ) print(out)  

Выход:

 val stat1 stat2 id date av con av con 0 50 1000 aa q122 10 40 100 900 1 50 1000 aa q222 0 50 0 1000 2 100 2000 bb q122 50 50 500 1500 3 100 2000 bb q222 25 75 100 1900  

Придумал более простой способ. Более того, вышеизложенное создает дубликаты столбцов:

 df = pd.read_clipboard() out = df.set_index(['stat1', 'stat2', 'id']) out.columns = out.columns.str.split("((av)|(con))", expand = True).droplevel([-2,-3]) out = out.stack(level=0) out.columns = [''.join(col) for col in out.columns] out = out.reset_index().rename(columns={'level_3':'date'})  

Выход:

 stat1 stat2 id date av av.1 con con.1 0 50 1000 aa q122 10 100 40 900 1 50 1000 aa q222 0 0 50 1000 2 100 2000 bb q122 50 500 50 1500 3 100 2000 bb q222 25 100 75 1900