У меня есть некоторый входной фрейм данных в качестве следующего примера:
import pandas as pd
df = pd.DataFrame(
{
"Name":["Ale", "Dan", "Hel"],
"Project": ["A", "A", "B"],
"10/04/2023 Formation": [24, 40, 40],
"17/04/2023 Formation": [12, 24, 24],
"10/04/2023 Holidays": [40, 40, 40],
"17/04/2023 Holidays": [12, 40, 24],
}
)
Как видно, некоторые столбцы представляют собой даты, относящиеся к определенному понятию (Формирование, Праздники, в данном случае).
Я хочу нормализовать эти столбцы, чтобы преобразовать их в строки (развернуть), но сохранить (группировать) каждый проект в своем собственном столбце; то есть я хотел бы выполнить преобразование фрейма данных, вывод которого будет примерно таким:
Date Name Project Formation Holidays
0 10/04/2023 Ale A 24 40
1 17/04/2023 Ale A 12 12
2 10/04/2023 Dan A 40 40
3 17/04/2023 Dan A 24 40
4 10/04/2023 Hel B 40 40
5 17/04/2023 Hel B 24 40
import pandas as pd
df = pd.DataFrame(
{
"Name":["Ale", "Dan", "Hel"],
"Project": ["A", "A", "B"],
"10/04/2023 Formation": [24, 40, 40],
"17/04/2023 Formation": [12, 24, 24],
"10/04/2023 Holidays": [40, 40, 40],
"17/04/2023 Holidays": [12, 40, 24],
}
)
# Unpivot the data using pd.melt()
df_melted = pd.melt(df, id_vars=["Name", "Project"], var_name = "Date_Concept", value_name = "Value")
# Separate the Date and Concept columns
df_melted[["Date", "Concept"]] = df_melted["Date_Concept"].str.split(" ", expand=True)
df_melted = df_melted.drop("Date_Concept", axis=1)
# Use pd.pivot_table() to reshape the dataframe
df_final = pd.pivot_table(df_melted, index=["Date", "Name", "Project"], columns = "Concept", values = "Value").reset_index()
# Reorder the columns
df_final = df_final[["Date", "Name", "Project", "Formation", "Holidays"]].sort_values(["Name", "Date", "Project"])
print(df_final)
Вы можете использовать pd.wide_to_long
после переименования столбцов для переключения информации префикса и суффикса (04.10.2023 г. -> Формирование-04.10.2023 г.):
out = pd.wide_to_long(df.rename(columns=lambda x: '-'.join(x.split(maxsplit=1)[::-1])),
stubnames=['Formation', 'Holidays'], i=['Name', 'Project'],
j='Date', sep='-', suffix='.*').reset_index()
Выход:
>>> out
Name Project Date Formation Holidays
0 Ale A 10/04/2023 24 40
1 Ale A 17/04/2023 12 12
2 Dan A 10/04/2023 40 40
3 Dan A 17/04/2023 24 40
4 Hel B 10/04/2023 40 40
5 Hel B 17/04/2023 24 24
Используя уборщика pivot_longer:
# pip install janitor
import janitor
out = df.pivot_longer(['Name', 'Project'], sort_by_appearance=True,
names_to=('Date', '.value'),
names_pattern=r'(\d{2}/\d{2}/\d{4}) (.*)')
Или names_sep=' '
вместо names_pattern=r'(\d{2}/\d{2}/\d{4}) (.*)'
.
Выход:
Name Project Date Formation Holidays
0 Ale A 10/04/2023 24 40
1 Ale A 17/04/2023 12 12
2 Dan A 10/04/2023 40 40
3 Dan A 17/04/2023 24 40
4 Hel B 10/04/2023 40 40
5 Hel B 17/04/2023 24 24