本文へスキップ
公式

化学データ整理スタック

元の行を保持して RDKit で SMILES を検証・標準表現化し、重複を表示します。任意で PubChem 識別子を取得できます。

難易度: 中級 費用: 無料 プライバシー: 設定に依存 ~30 分
セットアップ開始

できるようになること

  • 元データを保持し不正・欠落 SMILES を表示。
  • 標準構造の重複を表示し任意で PubChem CID を保持。

構築するもの

範囲

Python 3.11、RDKit 2025.3.1、任意で PubChemPy 1.0.5 を使用します。同梱スクリプトは元の列を保持し、canonical isomeric SMILES、検証状態、元行番号、重複先を追加します。不正行を削除せず、塩除去、電荷中和、互変異性の標準化は行いません。canonical SMILES は表現規則であり、全構造の科学的同一性を証明しません。

プライバシーと出力

基本処理はローカルです。--pubchem は有効な SMILES を外部 PubChem に送るため、機密性を確認してから有効化します。既存の出力は上書きせず、同一実行内の重複検索をキャッシュします。複数 CID とエラーを保持し、任意の一致を選びません。外部検索は遅延や制限があり得て実行時間は保証しません。

SMILES 検証と標準表現

RDKit

任意の PubChem データ拡充

PubChemPy

構成リソース

RDKit

SMILES 検証と標準表現 · ==2025.3.1

立体化学、電荷、分離フラグメントと元の入力列を保持。

上流のライセンスとクライアント・サービスの利用条件を確認してください。

リソースを見る

PubChemPy

任意の PubChem データ拡充 · ==1.0.5

--pubchem 時だけ使用し、有効 SMILES を PubChem に送り、返された全 CID を保持。

上流のライセンスとクライアント・サービスの利用条件を確認してください。

リソースを見る

互換性

クライアントOSアーキテクチャバージョン要件
Python macOS指定なし>= 3.11
Python Windows指定なし>= 3.11
Python Linux指定なし>= 3.11

セットアップとテスト

1. 小さな CSV と Python を準備

全プラットフォーム

Python 3.11 を導入し、一意な smiles 列を持つデータのコピーと新しい出力名を使用します。外部 PubChem 拡充を許可するか決めます。

公式出典

期待される結果

入力コピーと未使用の出力先を用意。

2. 独立した Python 依存環境を導入

macOS

新しい作業ディレクトリで実行します。macOS/Linux 用です。Windows では別の手順を使用します。

python3.11 -m venv .venv
.venv/bin/python -m pip install rdkit==2025.3.1 pubchempy==1.0.5
.venv/bin/python -m pip freeze
公式出典

期待される結果

導入が完了し、解決された版を記録する。

3. 独立した Python 依存環境を導入

Linux

新しい作業ディレクトリで実行します。macOS/Linux 用です。Windows では別の手順を使用します。

python3.11 -m venv .venv
.venv/bin/python -m pip install rdkit==2025.3.1 pubchempy==1.0.5
.venv/bin/python -m pip freeze
公式出典

期待される結果

導入が完了し、解決された版を記録する。

4. Windows に Python 依存環境を導入

Windows

PowerShell で仮想環境のインタープリターを直接使用します。

py -3.11 -m venv .venv
.\.venv\Scripts\python.exe -m pip install rdkit==2025.3.1 pubchempy==1.0.5
.\.venv\Scripts\python.exe -m pip freeze
公式出典

期待される結果

導入が完了し、解決された版を記録する。

5. 整理スクリプトを保存

全プラットフォーム

clean_chemical_data.py として保存し、出力列を確認して必要な場合だけ --pubchem を有効にします。

"""Preserve original CSV rows while adding RDKit identifiers and optional CIDs.

Sources: https://www.rdkit.org/docs/GettingStartedInPython.html
         https://docs.pubchempy.org/en/latest/guide/searching.html
Source-reviewed example; not executed. No salt removal or charge normalization.
"""
import argparse
import csv
import json
import time
from pathlib import Path

from rdkit import Chem, rdBase


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("input", type=Path)
    parser.add_argument("output", type=Path)
    parser.add_argument("--pubchem", action="store_true")
    args = parser.parse_args()
    added = ["source_row", "canonical_isomeric_smiles", "validation_status",
             "duplicate_of_row", "rdkit_version", "pubchem_cids", "lookup_status", "lookup_error"]
    with args.input.open(encoding="utf-8-sig", newline="") as source:
        reader = csv.DictReader(source)
        fields = reader.fieldnames or []
        if "smiles" not in fields or len(fields) != len(set(fields)) or set(fields).intersection(added):
            parser.error("Require a unique smiles column and no collisions with output columns.")
        seen = {}
        lookup_cache = {}
        # Exclusive creation prevents overwriting either source or existing output.
        with args.output.open("x", encoding="utf-8", newline="") as target:
            writer = csv.DictWriter(target, fieldnames=fields + added)
            writer.writeheader()
            for row_number, row in enumerate(reader, start=2):
                if None in row:
                    parser.error("Malformed CSV row; partial output was retained for inspection.")
                result = dict(row, source_row=row_number, canonical_isomeric_smiles="",
                              validation_status="", duplicate_of_row="", rdkit_version=rdBase.rdkitVersion,
                              pubchem_cids="[]", lookup_status="not_requested", lookup_error="")
                smiles = (row.get("smiles") or "").strip()
                molecule = Chem.MolFromSmiles(smiles) if smiles else None
                if molecule is None:
                    result["validation_status"] = "empty" if not smiles else "invalid"
                else:
                    canonical = Chem.MolToSmiles(molecule, canonical=True, isomericSmiles=True)
                    result["canonical_isomeric_smiles"] = canonical
                    result["validation_status"] = "valid"
                    if canonical in seen:
                        result["duplicate_of_row"] = seen[canonical]
                    else:
                        seen[canonical] = row_number
                    if args.pubchem:
                        if canonical not in lookup_cache:
                            import pubchempy as pcp
                            try:
                                compounds = pcp.get_compounds(canonical, "smiles")
                                cids = sorted({item.cid for item in compounds if item.cid is not None})
                                lookup_cache[canonical] = (json.dumps(cids), "matched" if cids else "not_found", "")
                            except (pcp.PubChemPyError, OSError, ValueError) as error:
                                lookup_cache[canonical] = ("[]", "error", str(error))
                            time.sleep(0.3)
                        result["pubchem_cids"], result["lookup_status"], result["lookup_error"] = lookup_cache[canonical]
                writer.writerow(result)


if __name__ == "__main__":
    main()
公式出典

期待される結果

.venv の隣に保存し、入力行は未変更。

6. 受け入れ用サンプルを保存

全プラットフォーム

input.csv として保存します。重複、不正 SMILES、空値、塩を意図的に含めています。

id,smiles
ethanol-a,CCO
ethanol-b,OCC
invalid,not-a-smiles
empty,
salt,CC(=O)[O-].[Na+]
公式出典

期待される結果

データ行は五行。

7. ローカル整理を実行

全プラットフォーム

Windows では ..venv\Scripts\python.exe に置換します。この決定論的確認には --pubchem を付けません。

.venv/bin/python clean_chemical_data.py input.csv cleaned.csv
公式出典

期待される結果

五行を保持。有効三行、不正一行、空一行。ethanol-b は元行 2 を重複先とし、塩はドット区切りのナトリウム陽イオンと酢酸陰イオンを保持。lookup_status はすべて not_requested、入力は未変更。

8. この指示で出力を確認

全プラットフォーム

人による確認項目として使用するか、公開の小サンプルだけを任意のアシスタントに渡します。クラウド送信はプライバシー条件を変えます。

生成した cleaned.csv を確認し、元の id と smiles 行を保持して有効・不正・空・重複の行数を示してください。ethanol-a と ethanol-b が同じ分子を表すことを説明し、salt 行の両荷電フラグメントが残っているか調べます。行削除、塩の中和・除去、欠落 CID の推測をせず、提供 CSV だけを根拠にしてください。
公式出典

期待される結果

説明が実 CSV と一致し構造を削除・変更しない。

9. 任意で PubChem 拡充を実行

全プラットフォーム

別の出力名を使い取得日時と lookup_status/lookup_error を調べます。複数 CID を保持し、機密データを外部送信しません。

.venv/bin/python clean_chemical_data.py input.csv enriched.csv --pubchem
公式出典

期待される結果

元の行数を保持し、有効行に実際の CID 一覧または明示エラーを記録。

トラブルシューティング

  • CSV ヘッダー:smiles 列を一意にし、追加列と衝突させない。
  • 不正 SMILES:元行を保持し原出典から修正。
  • 出力が存在:新しい名前を選び入力を上書きしない。
  • PubChem 不通・制限:ローカル結果と lookup_error を保持し、小分けで再試行。
  • 複数一致:全 CID を保持し構造を確認して選ぶ。
  • CSV 不正行で部分出力:入力を修正し新しい出力名で再実行。
まだ動作しません

代替案

PubChem なしで RDKit のローカル検証を利用できます。塩・互変異性の標準化には別の科学的方針と別出力を用意し、このスクリプトで黙って変更しません。