こんにちは。今回はPythonでデータをハッシュ化する方法についてまとめておこうと思います。
実際の業務でデータ分析を行う際には、個人情報などはマスクをかけて持ち出すケースもあるかと思います。そのような場合には、データをハッシュ化する方法が便利です。
ハッシュ化の方法
ハッシュ化には、hashlibというライブラリを使用します。こちらは、AnacondaでPython環境を構築していれば、デフォルトで使えるライブラリになっています。
import hashlib
## 利用できるハッシュ化アルゴリズムの確認
hashlib.algorithms_guaranteed
上記コマンド実行の結果、hashlibでは以下のアルゴリズムがサポートされていることが分かります。
'blake2b',
'blake2s',
'md5',
'sha1',
'sha224',
'sha256',
'sha384',
'sha3_224',
'sha3_256',
'sha3_384',
'sha3_512',
'sha512',
'shake_128',
'shake_256'
それでは、ある単一の文字列に対してハッシュ化を行います。
今回は、MD5によるハッシュ化を試してみます。MD5を利用したい場合は、hashlib.md5と書けば良いです。
str.encode()としている部分では、文字列をバイナリにエンコードし直している処理になります。
後ろのhexdigest()は、16進数文字列としてハッシュ化した結果を返す関数です。(hexdigest()以外にも、digest()などもあります。)
これで、以下のようにハッシュ値を得ることができました。
str = '12345'
hashed = hashlib.md5(str.encode()).hexdigest()
print(hashed)
## 実行結果
827ccb0eea8a706c4c34a16891f84e7b
それでは、次はこれを実際の分析データセット(DataFrameの形)に対して適用する方法と、パフォーマンスについても少し触れておこうと思います。
データフレームの特定列値のハッシュ化と実行速度
これはLambda関数を使って下記のように書けば良いです。
%%time
df = pd.DataFrame(index=np.arange(1000)) #1000行のデータフレームを生成
df["Name"] = "ABCDEFGHIJKLMNO" ##実験のため、1000件とも同じ名前で初期化
df["Name"] = df["Name"].apply(lambda x: hashlib.md5(x.encode()).hexdigest())
ちなみに、トータルの実行速度は以下の通りでした。
CPU times: user 3.07 ms, sys: 116 µs, total: 3.19 ms
Wall time: 3.1 ms
実際のデータセットでは数百万件、数千万件などもザラではありません。それくらいのボリュームにも耐えられるものなのか、下記、実験してみました。
%%time
## 1万件
df = pd.DataFrame(index=np.arange(10000))
df["Name"] = "ABCDEFGHIJKLMNO"
df["Name"] = df["Name"].apply(lambda x: hashlib.md5(x.encode()).hexdigest())
## 結果
CPU times: user 14.6 ms, sys: 740 µs, total: 15.4 ms
Wall time: 15 ms
%%time
## 10万件
df = pd.DataFrame(index=np.arange(100000))
df["Name"] = "ABCDEFGHIJKLMNO"
df["Name"] = df["Name"].apply(lambda x: hashlib.md5(x.encode()).hexdigest())
## 結果
CPU times: user 129 ms, sys: 6.35 ms, total: 135 ms
Wall time: 139 ms
%%time
## 100万件
df = pd.DataFrame(index=np.arange(1000000))
df["Name"] = "ABCDEFGHIJKLMNO"
print(df.info()) ##容量の確認
df["Name"] = df["Name"].apply(lambda x: hashlib.md5(x.encode()).hexdigest())
print(df.info()) ##容量の確認
## 結果
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 1 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Name 1000000 non-null object
dtypes: object(1)
memory usage: 15.3+ MB
None
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 1 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Name 1000000 non-null object
dtypes: object(1)
memory usage: 15.3+ MB
None
CPU times: user 1.26 s, sys: 133 ms, total: 1.39 s
Wall time: 1.39 s
%%time
## 1000万件
df = pd.DataFrame(index=np.arange(10000000))
df["Name"] = "ABCDEFGHIJKLMNO"
print(df.info())
df["Name"] = df["Name"].apply(lambda x: hashlib.md5(x.encode()).hexdigest())
print(df.info())
## 結果
<class 'pandas.core.frame.DataFrame'>
Int64Index: 10000000 entries, 0 to 9999999
Data columns (total 1 columns):
# Column Dtype
--- ------ -----
0 Name object
dtypes: object(1)
memory usage: 152.6+ MB
None
<class 'pandas.core.frame.DataFrame'>
Int64Index: 10000000 entries, 0 to 9999999
Data columns (total 1 columns):
# Column Dtype
--- ------ -----
0 Name object
dtypes: object(1)
memory usage: 152.6+ MB
None
CPU times: user 10.2 s, sys: 307 ms, total: 10.5 s
Wall time: 10.5 s
結果、実行速度は1000万行でも10秒程度と、かなり高速なように思います。件数が増えたからといって指数関数的に実行速度が伸びる訳でもないようでした。
また、ハッシュ化前後のデータフレームの容量も全く変わりませんでした。
上記のコードは、実際のデータ分析業務でも十分使えそうです。
以上、本日も最後までご覧いただきありがとうございました!
コメントを残す