SMILESの分子フィンガープリントへの変換をsklearnのPipelineに通せるようにsklearn風に書きました。
今回は一例でMACCSkeysに変換する場合です。
class MACCSkeysTransformer(BaseEstimator, TransformerMixin):
def __init__(self, smiles_column_name: str):
# smilesの構造が書かれた列名
self.smiles = smiles_column_name
def fit(self, X, y=None):
# fitでは何もしない
# fit内で下記transform内のコードを書いてもいいかも
return self
def transform(self, X):
# smilesをmaccskeysに変換
# その際リストに各maccskeysのbitを格納
df_maccs = X[self.smiles].map(lambda x: list(
MACCSkeys.GenMACCSKeys(Chem.MolFromSmiles(x))))
# リストに格納されたbitを展開
df_maccs = df_maccs.apply(pd.Series)
# 列名の変更
df_maccs.columns = ["maccskey_" + str(i) for i in df_maccs.columns]
return df_maccs
データフレーム内の要素のリストを展開する方法はこちらを参照。
.apply(pd.Series)でリストを展開できるのは面白い。
実際に使ってみる
データはtox21の化合物データ(データ数8014件)を使用しています。
%%time
mt = MACCSkeysTransformer("smiles")
df_tox_transform = mt.fit_transform(df_tox)
print("列数:", df_tox_transform.shape[1])
display(df_tox_transform.head(2))
想定通りに変換できてそう。私の環境では変換にかかった時間は約23秒でした。
続いてsklearnのPipelineに通してみる
pipe = Pipeline([
("mt", MACCSkeysTransformer("smiles")),
("ss", StandardScaler()),
])
df_tox_pipe = pipe.fit_transform(df_tox)
print("列数:", df_tox_pipe.shape[1])
print(df_tox_pipe)
最後に
フィンガープリントは様々な種類があるので、適宜コードは変えてください。