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

Pandas含重名列时np.where报错是否为预期行为?

问题分析与解答

可正常运行的代码示例

df = pd.DataFrame(np.random.randn(10,3),columns=['A','B','C'])
df['D'] = np.nan
for i in range(df.shape[1]-1):
    df['D'] = np.where(df.iloc[:,i] == df.min(axis=1), df.iloc[:,i].shift(-1), df['D'])
df

运行失败的代码示例(将列B改为A)

df = pd.DataFrame(np.random.randn(10,3),columns=['A','A','C'])
df['D'] = np.nan
for i in range(df.shape[1]-1):
    df['D'] = np.where(df.iloc[:,i] == df.min(axis=1), df.iloc[:,i].shift(-1), df['D'])
df

我的问题

即使未通过标签调用列A,出现该报错是否为np.where的预期行为?还是我编写的代码存在错误?

Jupyter中完整错误信息

ValueError Traceback (most recent call last)
<ipython-input-184-2ac8fa635230> in <module>
      5 df['D'] = np.where(df.iloc[:,i] == df.min(axis=1),
      6 df.iloc[:,i].shift(-1),
----> 7 df['D'])
      8 df

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py in __setitem__(self, key, value)
   2936 else:
   2937 # set column
-> 2938 self._set_item(key, value)
   2939
   2940 def _setitem_slice(self, key, value):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py in _set_item(self, key, value)
   2999 self._ensure_valid_index(value)
   3000 value = self._sanitize_column(key, value)
-> 3001 NDFrame._set_item(self, key, value)
   3002
   3003 # check if we are modifying a copy

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\generic.py in _set_item(self, key, value)
   3622
   3623 def _set_item(self, key, value) -> None:
-> 3624 self._data.set(key, value)
   3625 self._clear_item_cache()
   3626

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals\managers.py in set(self, item, value)
   1084 unfit_val_locs = []
   1085 removed_blknos = []
-> 1086 for blkno, val_locs in libinternals.get_blkno_placements(blknos, group=True):
   1087 blk = self.blocks[blkno]
   1088 blk_locs = blklocs[val_locs.indexer]

pandas\_libs\internals.pyx in get_blkno_placements()

pandas\_libs\internals.pyx in pandas._libs.internals.get_blkno_indexers()

ValueError: Buffer has wrong number of dimensions (expected 1, got 0)

咱们来拆解这个问题:

首先,这个报错不是np.where的预期行为,问题根源出在pandas对重复列名的内部处理机制上,你的代码逻辑本身没有错误,但忽略了pandas对列名的隐性依赖。

当DataFrame存在重复列名(比如两个'A')时,哪怕你用iloc按位置索引列,返回的Series依然会带有重复的列名'A'。在执行df['D'] = ...赋值操作时,pandas的内部数据块管理器(block manager)在处理数据维度时,会因为重复列名的存在出现混淆——它无法正确识别对应的数据块维度,最终抛出了维度不匹配的错误。

简单来说,pandas本身并不推荐使用重复列名,很多底层操作都会因为同名列出现异常,哪怕你用位置索引避开了直接调用列名,也绕不开内部对列名的校验和处理。

解决方法

  1. 最根本的方式:避免使用重复列名,给每个列分配唯一的标识,比如把第二个'A'改成'A2';
  2. 如果必须处理带重复列名的DataFrame,先给列重命名再执行逻辑:
# 重命名重复列
df.columns = ['A1', 'A2', 'C']
# 再执行你的原有代码逻辑
df['D'] = np.nan
for i in range(df.shape[1]-1):
    df['D'] = np.where(df.iloc[:,i] == df.min(axis=1), df.iloc[:,i].shift(-1), df['D'])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 19:22:31