Как развернуть фрейм данных Pandas в двух полях идентификатора с несколькими наборами столбцов

У меня есть Dataframe pandas, который выглядит так:

pid фид Имя первой причины ПерваяПричинаЗначение Имя второй причины ВтораяПричинаЗначение 1 'Икс' 'а' 3 'б' 8.2 2 'й' 'с' 8 'д' 7

Теперь я хочу отсоединить его от pid и fid, чтобы оно стало таким:

pid фид Причина Ценить 1 'Икс' 'а' 3 1 'Икс' 'б' 8.2 2 'й' 'с' 8 2 'й' 'д' 7

Как мне это сделать?

Вы читали раздел руководства пользователя об отмене поворота? Melt() и Wide_to_long(). Я совершенно уверен, что вы можете сделать это с помощью wide_to_long() после небольшой предварительной обработки.

wjandrea 12.07.2024 01:16
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Вы можете использовать Melt , а затем Pivot_table:

id_cols = ["pid", "fid"]

df = df.melt(id_vars=id_cols, var_name = "ReasonType", value_name = "Value")
df[["reason", "type"]] = df["ReasonType"].str.extract(r"(\w+Reason)(Name|Value)")
df = (
    df.pivot_table(
        index=id_cols + ["reason"], columns = "type", values = "Value", aggfunc = "first"
    )
    .reset_index()
    .drop(columns = "reason")
)
df.columns.name = None
   pid fid Name Value
0    1   x    a     3
1    1   x    b   8.2
2    2   y    c     8
3    2   y    d   7.0

Одним из эффективных маршрутов может быть использование janitor.pivot_longer, где вы передаете name_pattern для сопоставления столбцов на основе спецификации регулярного выражения:

# pip install pyjanitor
import janitor
import pandas as pd
df.pivot_longer(index=['pid','fid'], 
                names_to=['Reason','Value'], 
                names_pattern=['.+ReasonName','.+Value'])
   pid  fid Reason  Value
0    1  'x'    'a'    3.0
1    2  'y'    'c'    8.0
2    1  'x'    'b'    8.2
3    2  'y'    'd'    7.0

Альтернативно вы можете передать словарь в Names_pattern:

df.pivot_longer(index=['pid','fid'], 
                names_pattern = {'Reason':'.+ReasonName', 'Value':'.+Value'})
   pid  fid Reason  Value
0    1  'x'    'a'    3.0
1    2  'y'    'c'    8.0
2    1  'x'    'b'    8.2
3    2  'y'    'd'    7.0

В будущем выпуске будет предложена опция спецификации, в которой вы сможете еще более четко указать, как должна выглядеть итоговая таблица.

Вы можете избежать сторонней библиотеки и использовать для этого pd.stack:

temp = df.set_index(['pid','fid'])
columns = temp.columns.str.extract("(.+)Reason(.+)")
columns = pd.MultiIndex.from_frame(columns)
temp.columns=columns
(temp
.stack(level=0,future_stack=True)
.droplevel(-1)
.rename_axis(columns=None)
.rename(columns = {'Name':'Reason'})
.reset_index()
)
   pid  fid Reason  Value
0    1  'x'    'a'    3.0
1    1  'x'    'b'    8.2
2    2  'y'    'c'    8.0
3    2  'y'    'd'    7.0

Вы также можете использовать pd.lreshape:

groups = {'Reason':['FirstReasonName','SecondReasonName'], 
        'Value':['FirstReasonValue','SecondReasonValue']}

pd.lreshape(df,groups)
   fid  pid Reason  Value
0  'x'    1    'a'    3.0
1  'y'    2    'c'    8.0
2  'x'    1    'b'    8.2
3  'y'    2    'd'    7.0

Избегание процесса сложения/разложения, когда вы переключаетесь на длинную форму и обратно на широкую форму, если возможно, должно быть более производительным/эффективным.

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