【Pandas】列名が重複している列を取り除く方法[Python]

  • URLをコピーしました!
目次

Pandas

前回、Pythonのpickleライブラリを使ってオブジェクトをそのまま保存・読み込みする方法を紹介しました。

今回はPandasで列名が重複している列を取り除く方法を紹介します。

それでは始めていきましょう。

どういう時に列名が重複するのか?

まず列名が重複するのはどんな時か見てみましょう。

例えばデータフレームを一つ作って、そこに同じ列名で別のデータを追加した場合、列が書き換えられるだけで同じ列名の列が2つ存在するということにはなりません。

import pandas as pd

a = [1, 2, 3, 4, 5]
b = [2, 4, 6, 8, 10]

df = pd.DataFrame()
df["a"] = a

print(df)

df["a"] = b

print(df)

実行結果
   a
0  1
1  2
2  3
3  4
4  5
    a
0   2
1   4
2   6
3   8
4  10

ちなみに2回目に追加する場合は同じデータ数でないとエラーとなります。

import pandas as pd

a = [1, 2, 3, 4, 5]
b = [2, 4, 6, 8, 10, 12]

df = pd.DataFrame()
df["a"] = a

print(df)

df["a"] = b

print(df)

実行結果
   a
0  1
1  2
2  3
3  4
4  5
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[4], line 11
      7 df["a"] = a
      9 print(df)
---> 11 df["a"] = b
     13 print(df)

(中略)

ValueError: Length of values (6) does not match length of index (5)

列名が重複した列が発生するのは、例えばconcatなどを使い、2つのデータフレームを結合させた場合です。

import pandas as pd

a = [1, 2, 3, 4, 5]
b = [2, 4, 6, 8, 10]
c = [3, 6, 9, 12, 15]
d = [4, 8, 12, 16, 20]
e = [5, 10, 15, 20, 25]

df1 = pd.DataFrame({"a":a, "b":b, "c":c})
df2 = pd.DataFrame({"a":a, "d":d, "e":e})

df = pd.concat([df1, df2], axis=1)

print(df)

実行結果
   a   b   c  a   d   e
0  1   2   3  1   4   5
1  2   4   6  2   8  10
2  3   6   9  3  12  15
3  4   8  12  4  16  20
4  5  10  15  5  20  25

そして今回はこの重複した2つの列の1つを削除し、1つにするにはどうしたらいいかという問題です。

ちなみに重複した列名でデータを取得すると、両方の列が取得されます。

import pandas as pd

a = [1, 2, 3, 4, 5]
b = [2, 4, 6, 8, 10]
c = [3, 6, 9, 12, 15]
d = [4, 8, 12, 16, 20]
e = [5, 10, 15, 20, 25]

df1 = pd.DataFrame({"a":a, "b":b, "c":c})
df2 = pd.DataFrame({"a":a, "d":d, "e":e})

df = pd.concat([df1, df2], axis=1)

print(df["a"])

実行結果
   a  a
0  1  1
1  2  2
2  3  3
3  4  4
4  5  5

列名が重複した列を取り除く方法

列名が重複した列を取り除くには「df.loc[:, ~df.columns.duplicated()]」を使います。

import pandas as pd

a = [1, 2, 3, 4, 5]
b = [2, 4, 6, 8, 10]
c = [3, 6, 9, 12, 15]
d = [4, 8, 12, 16, 20]
e = [5, 10, 15, 20, 25]

df1 = pd.DataFrame({"a":a, "b":b, "c":c})
df2 = pd.DataFrame({"a":a, "d":d, "e":e})

df = pd.concat([df1, df2], axis=1)

df = df.loc[:,~df.columns.duplicated()]

print(df)

実行結果
   a   b   c   d   e
0  1   2   3   4   5
1  2   4   6   8  10
2  3   6   9  12  15
3  4   8  12  16  20
4  5  10  15  20  25

「df.loc[行, 列]」で特定の行、特定の列のデータが取得できます。

ちなみに行や列に「:」を使うと、全ての行、または全ての列になります。

そのため先ほどの「df.loc[:,~df.columns.duplicated()]」では、行は全ての行を取得しています。

そして列としては「~df.columns.duplicated()」を指定していますが、「~(チルダ)」のない「df.columns.duplicated()」では、各列が重複しているかしていないかをbool値(True/False)で取得できます。

そして「~(チルダ)」をつけるとその反対の結果が得られます。

この「~(チルダ)」の働きに関しては次回解説しますので、今回はそんなもんだと思ってもらえれば助かります。

ということでこんな感じ。

import pandas as pd

a = [1, 2, 3, 4, 5]
b = [2, 4, 6, 8, 10]
c = [3, 6, 9, 12, 15]
d = [4, 8, 12, 16, 20]
e = [5, 10, 15, 20, 25]

df1 = pd.DataFrame({"a":a, "b":b, "c":c})
df2 = pd.DataFrame({"a":a, "d":d, "e":e})

df = pd.concat([df1, df2], axis=1)

print(df.columns.duplicated())
print(~df.columns.duplicated())

実行結果
[False False False  True False False]
[ True  True  True False  True  True]

そして「df.loc[:,~df.columns.duplicated()]」ではこの結果が「True」になったところだけ取得されるため、重複していない列のみが取得されるというわけです。

ロガーで取ったデータなどを複数統合すると、どうしても時間の列など共通の列が複数存在してしまうので、そんな時に重複を削除するというのが非常に有用です。

次回は今回出てきた「~(チルダ)」が一体どういうものなのか色々と試してみたいと思います。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次