以前にこのようなつぶやきをしました。
そしたら知人がこのつぶやきを見つけて、結局どうやったらいいの?と聞かれたのでブログにまとめておきます。
実はすでに issue にあがっており RDKit の作者の Greg さんから解答もされています。
IPC を計算するときに avg=True
としたらいいよって言ってますね。
そもそも IPC ってなんじゃらほいって方はこちらをどうぞ。
Adjacency matrix に関する記述子なので大きい分子だと大きくなりそうなイメージですね。値が大きいと例えば sklearn
などで機械学習をするときにエラーが出ます。このエラーが曲者で
ValueError: Input contains NaN, infinity or a value too large for dtype('float64')
などと書いているもんですから、ついつい NaN
や Inf
ばっかり注目して探すけど「全然見つからない!なんで?」となってしまいます。
さて話を戻しますと、 avg=True
あるいは avg=1
とすると平均をとるような感じで IPC の値が小さくなるようです。
ついでに言うと RDKit 2D descriptor って計算するときに呼び出すモジュールがあっちこっちにあってめんどくさいですよね?なので私は以下のような自作ライブラリにラッパー関数を作ってます。
import pandas as pd
from rdkit.Chem import Descriptors
from rdkit.ML.Descriptors import MoleculeDescriptors
def calculate_descriptors(mols, names=None):
if names is None:
names = [d[0] for d in Descriptors._descList]
calc = MoleculeDescriptors.MolecularDescriptorCalculator(names)
descs = [calc.CalcDescriptors(mol) for mol in mols]
descs = pd.DataFrame(descs, columns=names)
return descs
計算する descriptor の名前を指定しなければ RDKit で計算できる 2D descriptor 全てを計算してくれます。今回の IPC の avg=True
をオプションとして組み込むならちょっとダサいけど以下のような感じでしょうか?
import pandas as pd
from rdkit.Chem import Descriptors
from rdkit.ML.Descriptors import MoleculeDescriptors
def calculate_descriptors(mols, names=None, ipc_avg=False):
if names is None:
names = [d[0] for d in Descriptors._descList]
calc = MoleculeDescriptors.MolecularDescriptorCalculator(names)
descs = [calc.CalcDescriptors(mol) for mol in mols]
descs = pd.DataFrame(descs, columns=names)
if 'Ipc' in names and ipc_avg:
descs['Ipc'] = [Descriptors.Ipc(mol, avg=True)
for mol in mols]
return descs
CalcDescriptors
class のソースコードを見てきましたが attribute などに descriptor を計算する関数を持っているのではなくその都度呼び出しているようで、関数を書き換えられません。そこで、一回 IPC を計算してその後 avg=True
で再計算した値で上書きしています。
ご参考になれば幸いです。
使い方の例の Gist ものせておきます。
RDKit (ver. 2018.09.1)