Suppose I have a dataframe with multiindex columns representing student majors and student GPAs. I want to find the class rank per major for each row. If the students had only one major each, then I could stack the major as another level of the multiindex and groupby(level=1).rank(). However, because the students can change their major, I have to have those as a separate feature for each year. What would be an efficient way to get the correct output? I know I could brute force it by iterating over the rows, but I'm hoping to avoid that as I may be dealing with a large amount of data.
Sample df:
categories = ['major', 'gpa']
students = ['Joe', 'Bob', 'Sara']
columns = pd.MultiIndex.from_product([categories, students])
index = range(4)
students_df = pd.DataFrame([['english', 'math', 'math', 3.8, 2.2, 3.7],
['english', 'math', 'math', 3.5, 2.4, 3.9],
['english', 'english', 'math', 3.5, 3.6, 3.9],
['english', 'english', 'math', 3.7, 3.5, 3.8],
], index=range(4), columns=columns)
print(students_df)
major gpa
Joe Bob Sara Joe Bob Sara
0 english math math 3.8 2.2 3.7
1 english math math 3.5 2.4 3.9
2 english english math 3.5 3.6 3.9
3 english english math 3.7 3.5 3.8
Expected Output
rank
Joe Bob Sara
0 1 2 1
1 1 2 1
2 2 1 1
3 1 2 1