はじめに
今回はサンプルとして適当に作った10個の化合物に対してMorganフィンガープリントを作成していきます。また、作ったデータセットに対して機械学習のインプットデータにすることを念頭に置いて全てが0の列の削除などのデータの前処理を行っていきます。
環境
- rdkit 2022.3.4
- pandas 1.2.5
- ipython 7.31.1
データの読み込み
# ライブラリーのインポート
import pandas as pd
import numpy as np
from IPython.display import SVG
from rdkit.Chem import AllChem, Draw, Descriptors, PandasTools
from rdkit.Chem import AllChem
from rdkit import Chem
以下のような化合物のSMILESが10個記載されたcsvファイルを今回はデータとして読み込みます。
# データ読み込み
df = pd.read_csv("sample_data.csv", index_col=0)
df
SMILESからMolオブジェクトを生成します(分子式の描画)
# SMILES→構造可視化
PandasTools.AddMoleculeColumnToFrame(df, "SMILES")
df
# エクセルに保存(エラー回避のため欠損値は0埋めしておく)
PandasTools.SaveXlsxFromFrame(df.fillna(0), "sample_data_withMol.xlsx", size=(150, 150))
Morganフィンガープリントの確認
どのようにMorganフィンガープリントが生成されるのか、ここではデータフレームの4番目の分子を例にとって確認してみましょう。
# 検討する分子の表示
m = Chem.MolFromSmiles(df["SMILES"][3])
m
# ビット数を定義
nBits=2048
# ビット情報を保持するための空の辞書を作っておく
bi = {}
# 半径2, ビット数2048(デフォルト)でフィンガープリントを作成
fp = AllChem.GetMorganFingerprintAsBitVect(m,2,nBits=nBits, bitInfo=bi)
# フィンガープリントの表示
list(fp.GetOnBits())
[1,
69,
204,
228,
268,
273,
283,
304,
389,
486,
650,
658,
695,
745,
807,
874,
940,
1057,
1088,
1152,
1199,
1380,
1385,
1423,
1665,
1750,
1873,
1917,
1985]
ここでフィンガープリントを1つ可視化してみましょう。
# リストの3番目のフィンガープリントを可視化する
img = Draw.DrawMorganBit(m, list(fp.GetOnBits())[2], bi)
img
複数の分子に対してMorganフィンガープリントを作成していく
# ビットを表現するデータフレームの作成
df_bits = pd.DataFrame(index = df.index, columns=np.arange(1,nBits+1))
df_bits
for i in range(len(df)):
m = Chem.MolFromSmiles(df["SMILES"][i])
fp = AllChem.GetMorganFingerprintAsBitVect(m,2,nBits=nBits)
# フィンガープリントが存在するビット数を"1"で埋める
for j in list(fp.GetOnBits()):
df_bits.iloc[i,j-1] = 1
df_bits
# NaNを0に変換する
df_bits = df_bits.fillna(0)
df_bits
# もともとのデータフレームとフィンガープリントの情報が入ったデータフレームを結合する
# 最初に読み込んだデータフレームには分子式が描画されているので、もう一度データを読み込み
df = pd.read_csv("sample_data.csv", index_col=0)
df_add = pd.concat([df, df_bits], axis=1)
df_add
# データの保存
df_add.to_csv("sample_data_withfp.csv")
データフレームの前処理
機械学習の用いるデータセットは一般的に前処理の段階で全て0や1もしくは同じ数値を持った列を除きます。そのような操作を実行していきます。
# 全て0の列を削除
def remove_all_zero_col(df):
df = df.copy()
for col in df.columns:
if (df[col] == 0).all():
df.drop(col, axis=1, inplace=True)
return df
df2 = remove_all_zero_col(df_add)
df2
# 全ての化合物に共通するビット数1873のフィンガープリントを確認
img_1873 = Draw.DrawMorganBit(m, 1873, bi)
img_1873
# 全て1の列を削除
def remove_all_one_col(df):
df = df.copy()
for col in df.columns:
if (df[col] == 1).all():
df.drop(col, axis=1, inplace=True)
return df
df3 = remove_all_one_col(df2)
df3
# この段階で保存
df3.to_csv("before.csv")
また機械学習では全て同じ値の説明変数は1つしか要らないので、説明変数が全て重複している列を取り除いていく。(行の重複を削除する方法を参考にする。列の重複を削除する方法は分かりませんでした。どなたかご存じであればコメントいただければ幸いです。)
まずは転置して行と列を入れ替えます。
df3.T
重複している行を確認します。
df3.T.duplicated()
df3.T.duplicated()
重複している行を削除します。
df4 = df3.T.drop_duplicates()
df4
再度転置して、もともと行だったデータを行に、もともと列だったデータを列に変換します。
new_df = df4.T
new_df
これにてデータの前処理は終了です。このデータフレームを用いて機械学習の予測モデルの構築などが出来そうです。
# 最終的なデータセットを保存
new_df.to_csv("after.csv")