You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python解析分子式提取元素含量生成字典与DataFrame

钙钛矿类分子式组分解析Python实现

需求说明

给定无嵌套括号的化学分子式(典型为钙钛矿组分式),解析得到各元素/基团对应的摩尔含量,规则如下:

  • 括号内所有组分的标注含量,需要乘以括号外侧紧邻的系数
  • 未明确标注含量的元素/基团,默认含量为1.00
  • 支持批量处理,最终生成可直接用于元素分析的Pandas DataFrame

示例输入:"FA0.85MA0.15Pb(I0.85Br0.15)3"
预期输出字典:{"FA":"0.85", "MA":"0.15", "Pb":"1.00", "I":"2.55", "Br":"0.45"}

覆盖典型测试输入:

  • "Cs0.05(MA0.17FA0.83)0.95Pb(I0.83Br0.17)3"
  • "CH3NH3PbI3"
  • "(CH3NH3)3Bi2I9"

实现思路

因为输入不存在嵌套括号,逻辑可以拆成3步实现:

  1. 用正则匹配所有带括号的片段,拆分出括号内的组分内容、括号外侧的系数,将括号内组分的含量乘系数后存入结果,同时把已处理的括号段从原字符串中移除
  2. 对移除所有括号后的平层字符串,用正则匹配所有「元素/基团+含量」配对,未标注含量的默认补1.00
  3. 相同元素/基团的含量做累加,最后统一按两位小数格式化,批量处理时将所有结果拼接为DataFrame即可

完整代码

依赖导入

import re
import pandas as pd
from collections import defaultdict

单分子式解析函数

def parse_formula(formula: str) -> dict:
    # 匹配括号段:分组1为括号内内容,分组2为括号后紧跟的系数
    bracket_pattern = re.compile(r'\(([^)]+)\)(\d+\.?\d*)')
    res = defaultdict(float)

    # 括号段替换逻辑:处理括号内组分乘系数,处理完后删除原括号段
    def replace_bracket(match):
        inner_content = match.group(1)
        coef = float(match.group(2))
        # 匹配括号内的「基团+含量」对
        item_pattern = re.compile(r'([A-Za-z0-9]+)(\d+\.?\d*)')
        for item_match in item_pattern.finditer(inner_content):
            symbol = item_match.group(1)
            val = float(item_match.group(2)) if item_match.group(2) else 1.0
            res[symbol] += val * coef
        return ''

    # 处理完所有括号段,剩余内容为括号外的平层组分
    flat_formula = bracket_pattern.sub(replace_bracket, formula)

    # 处理平层组分
    flat_pattern = re.compile(r'([A-Za-z0-9]+)(\d+\.?\d*)')
    for flat_match in flat_pattern.finditer(flat_formula):
        symbol = flat_match.group(1)
        val = float(flat_match.group(2)) if flat_match.group(2) else 1.0
        res[symbol] += val

    # 统一格式化为两位小数字符串,和示例输出格式对齐
    return {k: f"{v:.2f}" for k, v in res.items()}

批量处理生成DataFrame函数

def batch_parse_to_df(formula_list: list) -> pd.DataFrame:
    """
    输入分子式列表,返回索引为原分子式、列名为元素/基团、值为对应含量的DataFrame
    缺失组分含量默认填0.00
    """
    parsed_records = []
    for formula in formula_list:
        parsed = parse_formula(formula)
        parsed['formula'] = formula
        parsed_records.append(parsed)
    df = pd.DataFrame(parsed_records).set_index('formula').fillna("0.00")
    return df

测试验证

if __name__ == "__main__":
    test_formulas = [
        "FA0.85MA0.15Pb(I0.85Br0.15)3",
        "Cs0.05(MA0.17FA0.83)0.95Pb(I0.83Br0.17)3",
        "CH3NH3PbI3",
        "(CH3NH3)3Bi2I9"
    ]

    # 单条测试
    print(parse_formula(test_formulas[0]))
    # 输出: {'FA': '0.85', 'MA': '0.15', 'I': '2.55', 'Br': '0.45', 'Pb': '1.00'}

    # 批量生成DataFrame
    result_df = batch_parse_to_df(test_formulas)
    print(result_df)

测试输出的DataFrame结果:

formulaFAMAIBrPbCsCH3NH3Bi
FA0.85MA0.15Pb(I0.85Br0.15)30.850.152.550.451.000.000.000.00
Cs0.05(MA0.17FA0.83)0.95Pb(I0.83Br0.17)30.790.162.490.511.000.050.000.00
CH3NH3PbI30.000.003.000.001.000.001.000.00
(CH3NH3)3Bi2I90.000.009.000.000.000.003.002.00

注:如果对数值精度有要求,可以调整代码中小数保留的位数,浮点数计算的极小偏差不影响常规组分分析使用。

内容的提问来源于stack exchange,提问作者not_coding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:42:15