【Pandas】DataFrame間で重複する列名を取得する【Python】
MAX
MAX999blog
カラム(列)がマルチインデックスの場合、慣れないと扱いずらい。
そのため、カラムのマルチインデックスが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となっている。
列に対しては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に使う文字列は各列名に含まれていない文字列を使う方が良い。
reset_index(level=0)
みたいな感じのことをやる。
この方法でもDataFrame.columnsを置き換える。
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に変わる。
この方法だと、当然だが、列名が重複するので、それの対応も必要となる。
レベル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