#python #pandas #numpy
#питон #панды #тупица
Вопрос:
У меня есть образец фрейма данных df, в котором я хотел бы сохранить все столбцы в исходном наборе данных и создать новый сводный столбец на основе существующего набора данных. (сгруппировано по идентификатору) Исходный кадр данных содержит около 80 столбцов
Данные
s1 s2 id q122c q122a q122c2 q122a2 q222c q222a q222c2 q222a2 q322c q322a q322c2 q322a2 50 1000 aa 40 10 900 100 50 0 1000 0 60 -10 1100 -100 100 2000 bb 50 50 1500 500 75 25 1900 100 100 0 2000 0
Желанный
s1 s2 id date consumed1 avail1 consumed2 avail2 50 1000 aa q122 40 10 900 100 50 1000 aa q222 50 0 1000 0 50 1000 aa q322 60 -10 1100 -100 100 2000 bb q122 50 50 1500 500 100 2000 bb q222 75 25 1900 100 100 2000 bb q322 100 0 2000 0
Делающий
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])
Участник SO предоставил скрипт, который будет обрабатывать данные от широких до длинных, однако вывод, который я получаю, не захватывает все необходимые столбцы.
Любое предложение приветствуется.
Комментарии:
1. Почему у вас в выходных данных есть повторяющиеся столбцы?
2. позвольте мне обновить это @sammywemmy
3. круто, еще одна проверка, ваш входной фрейм данных также содержит повторяющиеся столбцы. это намеренно? если это так, пожалуйста, предоставьте способ его воспроизведения; как есть, использование
pd.read_clipboard
создает уникальные столбцы4. Я обновил @sammywemmy
Ответ №1:
Есть несколько способов сделать это:
Один из вариантов-преобразовать столбцы в мультииндекс, а затем изменить форму с помощью стека:
index = ['s1', 's2', 'id'] temp = df.set_index(index) temp.columns = temp.columns.str.split(r"([a|c]d?)", expand = True).droplevel(-1) temp.columns.names = ['date', None] (temp.stack(level='date') .rename(columns={'c':'consumed1', 'a':'avail1', 'c2':'consumed2', 'a2':'avail2'}) .reset_index() ) s1 s2 id date avail1 avail2 consumed1 consumed2 0 50 1000 aa q122 10 100 40 900 1 50 1000 aa q222 0 0 50 1000 2 50 1000 aa q322 -10 -100 60 1100 3 100 2000 bb q122 50 500 50 1500 4 100 2000 bb q222 25 100 75 1900 5 100 2000 bb q322 0 0 100 2000
с pd.wide_to_long
:
index = ['s1', 's2', 'id'] temp = df.set_index(index) temp.columns = temp.columns.str.split(r"([a|c]d?)").str[::-1].str[1:].str.join('_') (pd.wide_to_long(temp.reset_index(), stubnames = ['c', 'a', 'c2', 'a2'], i = index, j = 'date', sep='_', suffix='. ') .rename(columns={'c':'consumed1', 'a':'avail1', 'c2':'consumed2', 'a2':'avail2'}) .reset_index() ) s1 s2 id date consumed1 avail1 consumed2 avail2 0 50 1000 aa q122 40 10 900 100 1 50 1000 aa q222 50 0 1000 0 2 50 1000 aa q322 60 -10 1100 -100 3 100 2000 bb q122 50 50 1500 500 4 100 2000 bb q222 75 25 1900 100 5 100 2000 bb q322 100 0 2000 0
Другой вариант-с pivot_longer
помощью from pyjanitor
, который предлагает более простой способ для такой сложной перестройки :
#pip install pyjanitor import pandas as pd import janitor (df.pivot_longer(slice('s1', 'id'), names_to = ('date', '.value'), names_pattern = r"([a-z]d )(. )", sort_by_appearance=True) .rename(columns={'c':'consumed1', 'a':'avail1', 'c2':'consumed2', 'a2':'avail2'}) ) s1 s2 id date consumed1 avail1 consumed2 avail2 0 50 1000 aa q122 40 10 900 100 1 50 1000 aa q222 50 0 1000 0 2 50 1000 aa q322 60 -10 1100 -100 3 100 2000 bb q122 50 50 1500 500 4 100 2000 bb q222 75 25 1900 100 5 100 2000 bb q322 100 0 2000 0
names_pattern
Указывает, как будут изменены столбцы. в names_to
: («дата»,». значение») есть два значения. Есть также две группы регулярных names_pattern
выражений . Первая группа регулярных выражений будет сопряжена с date
формированием нового столбца, в то время как вторая группа регулярных выражений будет сопряжена с .value
формированием новых заголовков.
Комментарии:
1. Хорошо, дай мне попробовать. В моем полном наборе данных есть еще несколько столбцов, поэтому я думаю, что мог бы просто изменить переименование столбцов(с помощью последнего варианта). @sammywemmy Я также буду искать pyjanitor, спасибо тебе
2. Также используется ли «names_pattern’ для выделения даты, такой как «q122» и т. Д.? @сэмми вемми
3. да, поэтому первые значения сохраняются на сегодняшний день, остальные остаются в качестве заголовков столбцов
4. Ну молодец — проверю это спасибо
5. Я также обновил другие варианты; Pandas позволяет несколькими способами делать одно и то же; загвоздка в том, чтобы найти простые эффективные пути (простое всегда лучше).