ecetio's blog

データ品質と異常検知について。すべては個人的見解です。

簡単なFunctional Dependencies Violationの検知

functional dependencies(FDs)とは、データの列同士の関係において、ある列の組み合わせXがあった場合、別の列Aの値を一意に決定できることを言います。(X -> A)

例えば、「郵便番号」列があった場合、「住所」列の値が一意に決定できる場合、FDsであると言います。

これは、データ品質のうち、データセット内の「一貫性」の指標として利用されます。

例えば、「郵便番号」列の値1つにつき、「住所」列の値が2つ以上あれば、FDsについて逸脱があり、データの一貫性がないと判断されます。

opencleanというライブラリでは「fd_violation」という関数があり、FDsの逸脱を検知することがあります。また、SQLでもgroup byを用いて検知することもできます。

GitHub - VIDA-NYU/openclean: openclean - Data Cleaning and data profiling library for Python

ただし、opencleanは値の修復まで含み、関数の使い方がやや難しいことと、分析の中でSQLpythonを行き来するのが大変なため、簡単なFDsの検知スクリプトを作成しました。

github.com

簡単なデータ例

df = pd.DataFrame({'a':['A','A','C','D'],
                    'b':['AA','BB','CC','DD']})
df = df.astype({'a': 'string', 'b': 'string'})
groups = fd_violations(df, lhs='a', rhs='b')
df
a b
0 A AA
1 A BB
2 C CC
3 D DD

この場合、「a」列の値「A」について、「b」列の値が「AA」「BB」の2つとなるので、FDsの逸脱となります。 結果はdictで出力されます。

groups
{'A': Counter({'AA': 1, 'BB': 1})}

想定のデータが検知できています。 次に、もう少し現実的な例で実験してみます。 データはopencleanのテストデータを利用します。

datafile = 'data/jt7v-77mi.tsv'
df = pd.read_table(datafile)
df.head(5)
Plate ID Registration State Plate Type Meter Number Street Vehicle Body Type Vehicle Make Vehicle Color
661 FXY1858 NY PAS 407-3018 QUEENS BLVD SDN NISSA GY
780 89988JX NY COM 3 - FRESH POND TRD VAN FORD WHITE
901 FGX2747 NY PAS 504-3043 <NA> SDN HONDA SILVE
2287 23161JR NY COM 144-3942 WEST 42 STREET P-U FORD WHITE
2346 47153MC NY COM 144-3987 W 40TH ST SDN TOYOT SILV

スクリプトを実行すると、次のようになります。

groups = fd_violations(df, lhs='Meter Number', rhs='Street')
# 検出結果明細の表示
print('Meter Number | Street (Count)')
print('=============|===============')
for key in groups:
    conflicts = groups.get(key).most_common()
    street, count = conflicts[0]
    print('{:<12s} | {} x {}'.format(key, count, street))
    for street, count in conflicts[1:]:
        print('             | {} x {}'.format(count, street))
    print('-------------|---------------')
Meter Number | Street (Count)
=============|===============
144-3937     | 1 x WEST 42 STREET
             | 1 x WEST 42 ST
-------------|---------------
143-3785     | 2 x WEST 43RD ST
             | 1 x WEST 43 ST
-------------|---------------
144-6376     | 1 x 8TH AVE
             | 1 x 8TH AVENUE
-------------|---------------

さまざまなデータ品質の逸脱を検知するツールやアルゴリズムがありますが、現実的には一番よく使う手法かと思います。