pandas

【Pandas】カラムのマルチインデックスを解除する【Python】

MAX

カラム(列)がマルチインデックスの場合、慣れないと扱いずらい。

そのため、カラムのマルチインデックスが2種類ぐらいであれば、解除した方が操作しやすかったりする。

スポンサーリンク

データ準備

カラムがマルチインデックスのDataFrameを作成する。

1import pandas as pd
2
3# サンプルデータ作成
4# カラムがマルチインデックスのDataFrameを作成
5arrays = [
6    ['A', 'A', 'B', 'B'],
7    ['one', 'two', 'one', 'two']
8]
9tuples = list(zip(*arrays))
10index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
11df = pd.DataFrame([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], columns=index)
12
13print(df)
14# first    A       B    
15# second one two one two
16# 0        1   2   3   4
17# 1        5   6   7   8
18# 2        9  10  11  12

カラムはfirstとsecondのMultiIndexとなっている。

MultiIndexを解除する

列に対してはreset_indexを使えないので、新しい列名を作成し、columns自体を置き換える。

MultiInexの各レベルの値を「_」で結合したものを新しい列名にする。

1# マルチインデックスを解除
2df_flat = df.copy()
3# firstとsecondの値を_で結合したものを新しい列名とする。stripは余計な空白を削除する。
4df_flat.columns = ['_'.join(col).strip() for col in df.columns.values]
5
6print(df_flat)
7#    A_one  A_two  B_one  B_two
8# 0      1      2      3      4
9# 1      5      6      7      8
10# 2      9     10     11     12

この方法を使うと、MultiIndexを解除できるうえに列名が一意になる。

列名が長くなる場合もあるが、一意性が保たれるので、大抵の場合はこれが一番な気がする。

ただし、元の列の各値にjoinに使う文字列(今回の例の場合は「_」)が含まれていると、列名を色々操作する中で想定外の動作が起こる可能性があるため、joinに使う文字列は各列名に含まれていない文字列を使う方が良い。

MultiIndexの特定のレベルを削除する

reset_index(level=0)みたいな感じのことをやる。

この方法でもDataFrame.columnsを置き換える。

レベル0のカラムを削除

columns.droplevel(0)でレベル0のカラムを削除できる。

今回の例の場合はfirstが削除される。

1# 0レベルのカラムを削除
2df_droplevel0 = df.copy()
3df_droplevel0.columns = df.columns.droplevel(0)
4print(df_droplevel0)
5# second  one  two  one  two
6# 0         1    2    3    4
7# 1         5    6    7    8
8# 2         9   10   11   12
9print(df_droplevel0.columns)
10# Index(['one', 'two', 'one', 'two'], dtype='object', name='second')

カラムにはsecondのみが残る。

2種類(firstとsecond)から1種類(second)になったので、MultiIndexからIndexに変わる。

この方法だと、当然だが、列名が重複するので、それの対応も必要となる。

レベル1のカラムを削除

レベル0のカラムを削除するのと同様の方法。

1# 1レベルのカラムを削除
2df_droplevel1 = df.copy()
3df_droplevel1.columns = df.columns.droplevel(1)
4print(df_droplevel1)
5# first  A   A   B   B
6# 0      1   2   3   4
7# 1      5   6   7   8
8# 2      9  10  11  12

いずれにせよ、列名に重複が発生するので、後続の処理によっては対応が必要。

まとめ

やりたい後続の処理に合わせて、適切な方法を選ぶと良い。

1# マルチインデックスを解除
2df_flat = df.copy()
3# firstとsecondの値を_で結合したものを新しい列名とする。stripは余計な空白を削除する。
4df_flat.columns = ['_'.join(col).strip() for col in df.columns.values]
5
6# 0レベルのカラムを削除
7df_droplevel0 = df.copy()
8df_droplevel0.columns = df.columns.droplevel(0)
9
10# 1レベルのカラムを削除
11df_droplevel1 = df.copy()
12df_droplevel1.columns = df.columns.droplevel(1)
13

スポンサーリンク
ABOUT ME
MAX
MAX
ITエンジニア、データサイエンティスト
新卒でSIerに入社し、フリーランスになってWEB系へ転向。
その後AIの世界へ足を踏み入れ、正社員に戻る。 テーブルデータの分析がメイン。
スポンサーリンク
記事URLをコピーしました