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

使用Pandas loc赋值Pybel Molecule对象触发TypeError求助

解决Pandas.loc赋值Pybel Molecule对象时的TypeError问题

问题重现

我需要用Python结合Pybel把CSV里的数千条SMILES转成SDF,用Pandas处理数据时写了这段代码:

df['ROMol'] = None # 创建新列
for ind, row in df.iterrows():
      mol = pybel.readstring("smi", row[args.smi_column])
      df.loc[ind, 'ROMol'] = mol

示例CSV内容:

SMILES
C1=CC=CC=C1
CC(=O)Oc1ccccc1C(=O)O
C1CCCCC1

运行时直接抛出TypeError:

/pandas/core/indexing.py", line 1984, in _setitem_with_indexer_split_path elif len(ilocs) == 1 and lplane_indexer == len(value) and not is_scalar(pi): TypeError: object of type 'Molecule' has no len()

我已经通过先把Molecule对象存进列表再批量赋值解决了问题,但想搞懂怎么用.loc正确给单个单元格赋值。试过转列的dtype为object没用,也试了两种临时方法:

  • 把mol包成列表赋值:df.loc[ind, 'ROMol'] = [mol](能用但没解决根本问题)
  • 链式索引赋值:df["ROMol"][ind] = mol(能用但触发SettingWithCopyWarning)

错误原因

Pandas的.loc在处理赋值时,会尝试判断你传入的value是不是序列类型(比如列表、数组),判断逻辑里会调用len(value)。但Pybel的Molecule对象没实现__len__方法,导致触发这个TypeError。

正确解决方案

方法1:用.at代替.loc

.at是Pandas专门为单个单元格的标量赋值设计的API,不会做序列类型的检查,直接赋值即可:

df['ROMol'] = None # 创建新列
for ind, row in df.iterrows():
      mol = pybel.readstring("smi", row[args.smi_column])
      df.at[ind, 'ROMol'] = mol

方法2:用pd.Series包装标量值

如果你一定要用.loc,可以把Molecule对象包装成只包含单个元素的Series,明确告诉Pandas这是对应单个索引的值:

df.loc[ind, 'ROMol'] = pd.Series(mol, index=[ind])

更高效的批量处理方案

另外,对于数千条数据,用iterrows()循环效率很低,推荐用apply批量处理,既避免赋值问题又提升速度:

def smi_to_mol(smi):
    return pybel.readstring("smi", smi)

df['ROMol'] = df[args.smi_column].apply(smi_to_mol)

内容的提问来源于stack exchange,提问作者M.Vu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:52:37