I'm currently trying to pivot my pandas DataFrame by 'id' on '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
Depending on the max('rank'), I want to create as many 'years' columns and give them values according to the ascending rank
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
I tried my own solution (currently working, but I have ~2M rows and is not very effective)
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)
I know that it is not the optimal solution and is memory consuming, here is why I'm asking for a better solution
Thanks in advance
Use DataFrame.sort_values
with DataFrame.pivot
, sorting MultiIndex
by DataFrame.sort_index
and then flatten it by 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
While this doesn't mimic the exact output, a simpler approach involves performing a pivot right off the bat.
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
I personally don't like having numbers as my column headers, so I would:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With