【エラーメモ】qcut関数のエラーValueError: Bin edges must be unique

プログラムの実装時に遭遇したエラーを『エラーメモ』という形で残します。 簡易的にしかまとめませんが、誰かのお役に立てれば幸いです。

今回は、分位分析を実施する際(ビ二ング処理)に用いられる、pandasのqcut関数の利用時に遭遇したエラーです。

qcut関数とは?

下記サイトが大変参考になります。 いずれ自分でもまとめようと思っておりますので、お待ち下さい。

以下、簡単な使用例です。 数列[1,2,3,4,5]を3つに分割することを考えます。

import pandas as pd 
 
data = pd.DataFrame([1,2,3,4,5])
data.columns = ['val']
data['RNK'] = pd.qcut(data['val'], 3, labels=['Q1', 'Q2', 'Q3'])

特に問題なく、dataを3つに分割できました。

index val RNK
0 1 Q1
1 2 Q1
2 3 Q2
3 4 Q3
4 5 Q3
参考サイト

note.nkmk.me

エラー『Bin edges must be unique』とは?

どんなエラー?原因は?

数列[1,1,1,1,2]のような重複のある数列を、3つに分割することを考えます。 すると、次のようにBin edges must be uniqueのエラーが発生します。

import pandas as pd 
 
data = pd.DataFrame([1,1,1,1,2])
data.columns = ['val']
 
data['RNK'] = pd.qcut(data['val'], 3, labels=['Q1', 'Q2', 'Q3'])
#ValueError: Bin edges must be unique: array([1., 1., 1., 2.]).
#You can drop duplicate edges by setting the 'duplicates' kwarg

エラーの原因は、図のように重複のある数列部分に、分位点を設定できないこと、だと思われます。

f:id:guarana001:20191128230421p:plain:w300
重複のある数列

解決策は?

以下のサイト等を参考に簡単な解決策だけ、まとめました。 難しそうな方法もあるみたいなので、時間を見つけて追加します。(いつか)

①:発生順にランクづけする

rank(method='first')を用いて、ランクづけを行います。 重複がある場合も出現順にランクづけをするので、分割することが可能です。

import pandas as pd 
 
data = pd.DataFrame([1,1,1,1,2])
data.columns = ['val']
 
data['RNK'] = pd.qcut(data['val'].rank(method='first'), 3, labels=['Q1', 'Q2', 'Q3'])

以下のように、重複ある数列も、発生順に分割できます。

index val RNK
0 1 Q1
1 1 Q1
2 1 Q2
3 1 Q3
4 2 Q3
②:ノイズを加え、重複を解消する

重複のある数列にノイズを加え、重複を解消します。

今回は、平均0標準偏差1e-3の正規分布から発生したノイズを加えます。

import numpy as np
import pandas as pd
 
data = pd.DataFrame([1,1,1,1,2])
eps = 1e-3
data = data + np.random.normal(0, eps, data.shape)
data.columns = ['val'] 
 
data['RNK'] = pd.qcut(data['val'], 3, labels=['Q1', 'Q2', 'Q3'])

以下のように、重複ある数列も分割できます。

index val RNK
0 0.999253 Q1
1 1.001692 Q3
2 1.000051 Q2
3 0.999363 Q1
4 2.000191 Q3
参考サイト

ailaby.com

stackoverflow.com