У меня есть Dataframe pandas, который выглядит так:
Теперь я хочу отсоединить его от pid
и fid
, чтобы оно стало таким:
Как мне это сделать?
Вы можете использовать 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
Избегание процесса сложения/разложения, когда вы переключаетесь на длинную форму и обратно на широкую форму, если возможно, должно быть более производительным/эффективным.
Вы читали раздел руководства пользователя об отмене поворота? Melt() и Wide_to_long(). Я совершенно уверен, что вы можете сделать это с помощью
wide_to_long()
после небольшой предварительной обработки.