У меня есть фрейм данных pandas, и мне нужно «переключить» строку и столбцы. (транспонировать? поворачивать? плавить? понятия не имею, как это называется):
Допустим, у меня есть 2 ссылки, каждая ссылка имеет 4 шага, каждый шаг имеет 3 переменные.
df = pd.DataFrame({'ref': ['ref1', 'ref1', 'ref1', 'ref1', 'ref2', 'ref2', 'ref2', 'ref2'],
'step': [1, 2, 3, 4, 1, 2, 3, 4],
'var_1': [5, 7, 7, 9, 12, 9, 87, 90],
'var_2': [11, 8, 10, 6, 6, 9, 12, 9],
"var_3": [11, 8, 10, 6, 6, 9, 12, 9]})
Я хочу преобразовать этот df в эту форму:
df = pd.DataFrame({'ref': ['ref1', 'ref2'],
> 'step 1 - var_1': [5, 12],
> 'step 1 - var_2': [11, 6],
> 'step 1 - var_3': [11, 6],
> 'step 2 - var_1': [7, 12],
> 'step 2 - var_2': [8, 9],
> 'step 2 - var_3': [8, 9]})
На df ниже я пробовал методы (и они работали):
(df
.pivot_wider(
index='ref',
names_from='step',
values_from = ['var_1', 'var_2', 'var_3'],
names_glue = "step {step} - {_value}")
.sort_index(axis=1)
)
# and also
df_out = df.pivot(index='ref', columns='step').sort_index(level=1, axis=1)
df_out.columns = [f'step {j} - {i}' for i, j in df_out.columns]
Фактический df выглядит так:
Но они не работают с моим фактическим df, у меня есть код ошибки: «ValueError: индекс содержит повторяющиеся записи, не может изменить форму»
Последнее редактирование: у «уникального идентификатора» моего df был дубликат, теперь он работает, спасибо всем за ваш ответ. Сегодня узнал много нового :)
Заранее спасибо, Лучший
Редактировать: формат и изображения
Судя по выходным столбцам, вы можете захотеть df.explode('step'), а затем rename(), но значения строк этому не соответствуют.
Использовать:
df[df.step<3].set_index(['ref','step']).unstack()
Выход:
var_1 var_2 var_3
step 1 2 1 2 1 2
ref
ref1 5 7 11 8 11 8
ref2 12 9 6 9 6 9
Это хороший подход, но необходимо изменить заголовки столбцов, чтобы они соответствовали запросу OP.
Попробуйте это, используя новый оператор «морж» в однострочном коде:
(df_new := df.set_index(['ref', 'step']).unstack().sort_index(level=1, axis=1))\
.set_axis([f'step {j} - {i}' for i, j in df_new.columns], axis=1)
Выход:
step 1 - var_1 step 1 - var_2 step 1 - var_3 step 2 - var_1 step 2 - var_2 step 2 - var_3 step 3 - var_1 step 3 - var_2 step 3 - var_3 step 4 - var_1 step 4 - var_2 step 4 - var_3
ref
ref1 5 11 11 7 8 8 7 10 10 9 6 6
ref2 12 6 6 9 9 9 87 12 12 90 9 9
Подробности:
set_index
со столбцами ref и stepunstack
шаг для перехода в столбцыsort_index
set_axis
и список
понимание с форматированием f-строкиАльтернативный способ с тем же выходом, что и выше,
df_out = df.pivot(index='ref', columns='step').sort_index(level=1, axis=1)
df_out.columns = [f'step {j} - {i}' for i, j in df_out.columns]
Привет, спасибо за ваш ответ, у меня есть эта ошибка, когда я запускаю код: «Индекс содержит повторяющиеся записи, не может изменить форму», знаете ли вы, почему?
Да, у вас есть несколько записей с ref и step, вам нужно будет сделать groupby или pivot_table с каким-то агрегированием для обработки нескольких записей.
Хитрость заключается в использовании df.pivot. Вы можете выбрать index='ref' и columns='step':
new = df.pivot(index='ref', columns='step')
Полученная таблица имеет мультииндекс для ref и несколько столбцов. В мультистолбце есть информация о шаге и переменной, поэтому мы можем использовать ее для создания новых заголовков столбцов. Наконец, мы можем сбросить индекс:
new.columns = [f'step {x[1]} - {x[0]}' for x in new.columns]
new = new.reset_index()
Привет, SNygard, я попробовал ваш метод, но у меня есть код ошибки: «ValueError: индекс содержит повторяющиеся записи, не может изменить форму». Я отредактировал свой вопрос с подробностями, если это может помочь :)
Один из вариантов — pivot_wider из pyjnanitor, чтобы абстрагироваться от переименования столбца с помощью параметра names_glue:
# pip insall pyjanitor
import pandas as pd
import janitor
(df
.pivot_wider(
index='ref',
names_from='step',
values_from = ['var_1', 'var_2', 'var_3'],
names_glue = "step {step} - {_value}")
.sort_index(axis=1)
)
ref step 1 - var_1 step 1 - var_2 step 1 - var_3 ... step 3 - var_3 step 4 - var_1 step 4 - var_2 step 4 - var_3
0 ref1 5 11 11 ... 10 9 6 6
1 ref2 12 6 6 ... 12 90 9 9
[2 rows x 13 columns]
Names_glue допускает комбинацию параметров values_from и names_from — в приведенном выше коде {step} — это аргумент name_from, а {_value} — заполнитель для values_from
Если мы строго придерживаемся вашего вывода, то фильтр должен выполняться в столбце step только для значений меньше 3:
(df
.loc[df.step < 3]
.pivot_wider(
index='ref',
names_from='step',
names_glue = "step {step} - {_value}")
.sort_index(axis=1)
)
ref step 1 - var_1 step 1 - var_2 step 1 - var_3 step 2 - var_1 step 2 - var_2 step 2 - var_3
0 ref1 5 11 11 7 8 8
1 ref2 12 6 6 9 9 9
Привет, это именно то, чего я хочу добиться, спасибо :) Я получил эту ошибку, когда запускаю ее для своих данных: «Индекс содержит повторяющиеся записи, не может изменить форму». Я пытался удалить другие столбцы, чтобы избежать помех, но это не сработает, есть идеи?
Вам, возможно, придется создать еще один столбец, который сделает ваши данные уникальными - пожалуйста, обновите свой вопрос, чтобы отразить повторяющиеся записи с ожидаемым результатом
Я обновил свой вопрос, я создал столбец «ссылка», который будет уникальным после завершения преобразования.
Пожалуйста, поделитесь текстом, а не фотографиями. Вместо этого поделитесь файлом excel, если U csn
Как вход соотносится с выходом?