#python #python-3.x #pandas #pivot
#python #python-3.x #pandas #поворот
Вопрос:
В настоящее время я пытаюсь повернуть фрейм данных pandas по ‘id’ в ‘rank’
print(df)
id rank year
0 key0 1 2011
1 key0 2 2012
2 key0 3 2013
3 key1 1 2014
4 key1 2 2015
5 key1 3 2016
6 key2 1 2017
7 key2 2 2018
8 key2 3 2019
В зависимости от max (‘rank’) я хочу создать столько столбцов ‘years’ и присвоить им значения в соответствии с возрастающим рангом
print(df)
id rank1 year1 rank2 year2 rank3 year3
0 key0 1 2011 2 2012 3 2013
1 key1 1 2014 2 2015 3 2016
2 key2 1 2017 2 2018 3 2019
Я попробовал свое собственное решение (в настоящее время работает, но у меня ~ 2 м строк и оно не очень эффективно)
df2= df.melt(id_vars=["id", "rank"], value_vars=[elem for elem in df.columns if elem not ['id','rank']])
df2['col_name'] =df2['variable'] (df2['rang']-1).astype('str')
df2.value.fillna(0, inplace = True)
df2= pd.pivot_table(df2, index=["id"], columns=["col_name"], values="value", aggfunc=max)
Я знаю, что это не оптимальное решение и потребляет много памяти, вот почему я прошу лучшего решения
Заранее спасибо
Комментарии:
1.
df.pivot(index="id",columns="rank", values=["year","rank"])
?
Ответ №1:
Используйте DataFrame.sort_values
с DataFrame.pivot
, сортируя MultiIndex
по DataFrame.sort_index
, а затем сгладьте его по f-string
s:
df1 = (df.sort_values(['id','rank'])
.pivot(index="id",columns="rank", values=["year","rank"])
.sort_index(axis=1, level=1))
df1.columns = [f'{a}{b}' for a, b in df1.columns]
df1 = df1.reset_index()
print (df1)
id rank1 year1 rank2 year2 rank3 year3
0 key0 1 2011 2 2012 3 2013
1 key1 1 2014 2 2015 3 2016
2 key2 1 2017 2 2018 3 2019
Ответ №2:
Хотя это не имитирует точный результат, более простой подход предполагает выполнение поворота сразу.
df.pivot(index="id", columns="rank", values="year")
rank 1 2 3
id
key0 2011 2012 2013
key1 2014 2015 2016
key2 2017 2018 2019
Лично мне не нравится иметь числа в качестве заголовков столбцов, поэтому я бы:
df.pivot(index="id", columns="rank", values="year").rename(columns="rank_{}".format)
rank rank_1 rank_2 rank_3
id
key0 2011 2012 2013
key1 2014 2015 2016
key2 2017 2018 2019
Комментарии:
1. Все работает нормально, спасибо! Мне просто нужно выяснить, как изменить имя с несколькими индексами, если я добавлю несколько столбцов
2. Самый простой способ переименовать уровни мультииндексного с помощью метода Dataframe rename_axis
Ответ №3:
Вы можете сделать это:
f=pd.DataFrame()
for name,group in df.groupby('rank'):
group=group.rename(columns={'rank':'rank{}'.format(name),'year':'year{}'.format(name)})
f=pd.concat([f.reset_index(drop=True),group.reset_index(drop=True)],axis=1)
#then, drop duplicate columns
f = f.loc[:,~f.columns.duplicated()]
f
id rank1 year1 rank2 year2 rank3 year3
0 key0 1 2011 2 2012 3 2013
1 key1 1 2014 2 2015 3 2016
2 key2 1 2017 2 2018 3 2019
Ответ №4:
Давайте используем .unstack
with cumcount()
для создания псевдоиндекса перед отключением и sort_index()
.
Также предполагается, что ваш столбец ранга уже отсортирован.
df1 = df.set_index(['id',df.groupby('id').cumcount() 1]).unstack(1).sort_index(1,1)
#flatten columns.
df1.columns = [f'{x}_{y}' for x,y in df1.columns]
print(df1)
rank_1 year_1 rank_2 year_2 rank_3 year_3
id
key0 1 2011 2 2012 3 2013
key1 1 2014 2 2015 3 2016
key2 1 2017 2 2018 3 2019