<jupyter_start><jupyter_text>7. Handling a MultiIndexA MultiIndex or multi-level index is a cumbersome addition to a Pandas DataFrame that occasionally makes data easier to view, but often makes it much more difficult to manipulate. You usually encounter a MultiIndex after a `groupby` operation with multiple grouping columns or multiple aggregating columns.<jupyter_code>import pandas as pd
college = pd.read_csv('data/college.csv')
college.head()<jupyter_output><empty_output><jupyter_text>Let's use a result similar to the one at the end of the previous notebook, except this time group by both state and religious affiliation.<jupyter_code>df = college.groupby(['stabbr', 'relaffil']).agg({'satmtmid': ['min', 'max'],
                                                  'satvrmid': ['min', 'max'],
                                                  'ugds': 'mean'}).round(0)
df.head(10)<jupyter_output><empty_output><jupyter_text>A MultiIndex in both the index and columnsBoth the rows and columns have a MultiIindex with two levels. Let's verify their types.<jupyter_code>type(df.index)
type(df.columns)<jupyter_output><empty_output><jupyter_text>Selection and further processing is difficult with a MultiIndexThere is no magic extra functionality that a MultiIndex possesses (outside of some trickery). They are harder to remember how to make selections from and more difficult to call other methods on. I suggest working with DataFrames that have a simpler, single-level index. Convert to a single level index - Rename the columns and reset the indexWe can convert this DataFrame so that only single-level indexes rename. There is no direct way to rename columns of a DataFrame during a groupby (yes, something so simple is impossible with pandas), so we must overwrite them manually. Let's do that now.<jupyter_code>df.columns = ['min satmtmid', 'max satmtmid', 'min satvrmid', 'max satvrmid', 'mean ugds']
df.head()<jupyter_output><empty_output><jupyter_text>From here, we can use the `reset_index` method to make each index level an actual column.<jupyter_code>df_final = df.reset_index()
df_final.head()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07936507936507936, 'fraction_numerical': 0.0018674136321195146, 'mean_word_length': 4.639473684210526, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '481047', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 598, 'n_tokens_neox': 573, 'n_words': 244, 'path': '7. Handling a MultiIndex.ipynb', 'repo_name': 'MathMachado/Minimally-Sufficient-Pandas', 'size': '2142'}