Python:从分子式字符串提取原子计数并存储到DataFrame
嘿,我来帮你搞定这个分子式原子计数提取的问题!
你遇到的问题主要出在两个地方:一是str.extract返回的是DataFrame而非Series,直接赋值会导致数据类型异常,进而让S、Cl这类原子的计数无法正确提取;二是原正则没有考虑双字母原子(比如Cl、Br)的匹配逻辑,也没统一处理原子后无数字的情况(默认计数应为1)。
我给你写了个更通用且优雅的解决方案,既能覆盖单/双字母原子,还能自动处理无数字的原子计数:
import pandas as pd import re # 读取你的数据 myfile = "whatever.csv" data = pd.read_csv(myfile, sep='|', header=0) # 注意:双字母原子要放在单字母前面,避免正则先匹配到单字母(比如先匹配Cl,而不是先匹配C) target_atoms = ['Cl', 'Br', 'Na', 'C', 'H', 'O', 'N', 'S'] # 正则模式:匹配双字母原子(如Cl)或单字母大写原子(如C),后面跟可选的数字 formula_pattern = re.compile(r'([A-Z][a-z]?)(\d*)') def parse_formula(formula_str): # 捕获所有原子和对应的计数 atom_matches = formula_pattern.findall(formula_str) # 构建计数字典:无数字的原子默认计数为1 count_dict = {atom: int(num) if num else 1 for atom, num in atom_matches} # 返回目标原子的计数,不存在的原子返回0 return pd.Series([count_dict.get(atom, 0) for atom in target_atoms], index=target_atoms) # 批量处理所有分子式,生成原子计数列 atom_count_df = data['molecular_formula'].apply(parse_formula) # 合并到原数据中 data = pd.concat([data, atom_count_df], axis=1) # 可选:确保原子列为整数类型 data[target_atoms] = data[target_atoms].astype(int)
这个方案的优势:
- 通用匹配:正则
([A-Z][a-z]?)(\d*)能自动识别单字母和双字母原子,不用单独为每种原子写正则; - 自动处理无数字情况:如果原子后面没跟数字(比如分子式里的
Cl),会自动设为1; - 高效简洁:用
apply批量处理,比你之前的逐行loc操作高效得多,也更易维护; - 符合需求:原子不存在时默认返回0,完全满足你的要求。
用你给出的示例分子式C55H85N17O25S4测试,会得到你期望的输出:
| molecular_formula | C | H | O | N | Cl | S | Br |
|---|---|---|---|---|---|---|---|
| C55H85N17O25S4 | 55 | 85 | 25 | 17 | 0 | 4 | 0 |
你之前的临时解决方案虽然能工作,但代码冗余且容易遗漏情况,这个方法能一次性解决所有问题~
内容的提问来源于stack exchange,提问作者thiR
相关产品推荐
相关产品推荐

