Предположим, что у меня есть следующий фрейм данных в pandas: фрейм данных
и я хочу преобразовать его в следующее: преобразованный фрейм данных
Как мне это сделать?
Я пытался выполнить транспонирование, pd.wide_to_long, pd.melt, но они выдают ошибки. Я новичок в этом и мне нужна помощь, пожалуйста!
Обновление: у меня есть ответы, спасибо всем, кто ответил. <3 Я удалил набор данных сейчас, так как у меня уже есть рабочее решение.
@Rawson Я прикрепил ссылку на набор данных.





Вы можете использовать следующий код для воссоздания выходного фрейма данных из исходного изображенного фрейма данных (первые несколько строк просто воссоздают ваш фрейм данных).
import pandas as pd
# recreating your starting dataframe
df = pd.read_csv(r"C:\...\bmi.csv", index_col=0)
df = df.iloc[2:, :] # drop first 2 rows to match your initial picture
# Change column names to just the year
df.columns = pd.Series(df.columns).str.split(".", n=1, expand=True)[0]
# and add the first row
df.columns = pd.MultiIndex.from_tuples(list(zip(df.columns,
df.iloc[0].str.lstrip())))
# then remove first row
df = df.iloc[1:]
# stack the first level of the MultiIndex column (year), and sort the index
df = df.stack(level=0).sort_index(level=[0, 1], ascending=[True, False])
# in each column...
for col in df.columns:
# ...extract the float at the start of the string (and convert to float)
df[col] = df[col].str.extract(r'(\d+\.\d+)', expand=False).astype(float)
Дайте знать, если у вас появятся вопросы.
Большое спасибо! Оно работает! <3
Возможное решение:
df = (
pd.read_csv("bmi.csv", index_col=0, header=[0,3], na_values = "No data")
.replace("\s+.+", "", regex=True).stack(0, dropna=False)
.astype(float).reset_index(level=0, names = "Country").pipe(
lambda x: x.set_axis(x.index.str.split(".").str[0]))
.groupby([pd.Grouper(level=0), "Country"], sort=False).first()
.reset_index(names=["Year", "Country"]).rename_axis(columns=None)
.sort_values(by=["Country", "Year"], ascending=[True, False])
.reset_index(drop=True)
)
Выход :
print(df)
Year Country Both sexes Female Male
0 2016 Afghanistan 23.0 23.7 22.3
1 2015 Afghanistan 22.9 23.6 22.3
2 2014 Afghanistan 22.8 23.5 22.2
3 2013 Afghanistan 22.8 23.4 22.1
4 2012 Afghanistan 22.7 23.3 22.0
... ... ... ... ... ...
8143 1979 Zimbabwe 22.0 23.6 20.3
8144 1978 Zimbabwe 21.9 23.6 20.2
8145 1977 Zimbabwe 21.9 23.5 20.2
8146 1976 Zimbabwe 21.8 23.5 20.1
8147 1975 Zimbabwe 21.8 23.5 20.0
[8148 rows x 5 columns]
Да, это работает именно так, как я хочу! Большое спасибо! <3
Предоставьте образец вашего фрейма данных, который можно легко скопировать, например, с помощью
df.head().to_dict().