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

Pandas遍历行计算赋值失效问题及修复求助

问题描述
  • 需求:遍历DataFrame的每一行,当source字段值为HR(对应类别“HR contacts”)时,若total number≤500则保留全部数值,否则保留500并计算剩余数值。
  • 问题:使用iterrows()循环赋值后,新增的keep #和rest #列仍全部为NaN;改用iloc循环的方式也未解决。

用户提供的代码片段:
第一段代码:

cntByUserNm['keep #'] = np.nan
cntByUserNm['rest #'] = np.nan
for index, row in cntByUserNm.iterrows():
    print(row['Owner Name'], row['source'])
    if row['source'] == 'HR':
        if row['total number'] <= 500:
            row['keep #'] = row['total number']
            row['rest #'] = 0
        else:
            row['keep #'] = 500
            row['rest #'] = row['total number'] - 500

第二段尝试代码:

for i in range(0, len(cntByUserNm)):
    print(cntByUserNm.iloc[i]['Owner Name'], cntByUserNm.iloc[i]['blizday source'])
    if cntByUserNm.iloc[i]['blizday source'] == mainCat:
        if cntByUserNm.iloc[i][befCnt] <= destiNum:
            cntByUserNm.iloc[i]['keep #'] = cntByUserNm.iloc[i][befCnt]
            cntByUserNm.iloc[i]['rest #'] = 0
        else:
            cntByUserNm.iloc[i]['keep #'] = destiNum
            cntByUserNm.iloc[i]['rest #'] = cntByUserNm.iloc[i][befCnt] - destiNum
修复方法

问题根源

  • iterrows()返回的row是原DataFrame的副本,修改副本不会同步到原DataFrame,因此赋值无效。
  • iloc[i]['列名']属于链式索引,可能返回原数据的视图或副本,直接赋值可能无法修改原DataFrame,还会触发SettingWithCopyWarning。

方法1:修正iterrows()循环赋值

通过loc[index, 列名]直接修改原DataFrame,避免操作副本:

import numpy as np

cntByUserNm['keep #'] = np.nan
cntByUserNm['rest #'] = np.nan
for index, row in cntByUserNm.iterrows():
    print(row['Owner Name'], row['source'])
    if row['source'] == 'HR':
        if row['total number'] <= 500:
            cntByUserNm.loc[index, 'keep #'] = row['total number']
            cntByUserNm.loc[index, 'rest #'] = 0
        else:
            cntByUserNm.loc[index, 'keep #'] = 500
            cntByUserNm.loc[index, 'rest #'] = row['total number'] - 500

方法2:修正iloc循环赋值

使用iloc[i, 列索引]的方式直接定位修改,避免链式索引问题:

for i in range(len(cntByUserNm)):
    print(cntByUserNm.iloc[i]['Owner Name'], cntByUserNm.iloc[i]['blizday source'])
    if cntByUserNm.iloc[i]['blizday source'] == mainCat:
        # 获取列的索引位置
        keep_col_idx = cntByUserNm.columns.get_loc('keep #')
        rest_col_idx = cntByUserNm.columns.get_loc('rest #')
        current_val = cntByUserNm.iloc[i][befCnt]
        
        if current_val <= destiNum:
            cntByUserNm.iloc[i, keep_col_idx] = current_val
            cntByUserNm.iloc[i, rest_col_idx] = 0
        else:
            cntByUserNm.iloc[i, keep_col_idx] = destiNum
            cntByUserNm.iloc[i, rest_col_idx] = current_val - destiNum

方法3:推荐使用向量化操作(高效无循环)

Pandas的向量化操作比循环效率高得多,尤其适合大数据量场景,同时避免副本/视图问题:

import numpy as np

# 初始化列
cntByUserNm['keep #'] = np.nan
cntByUserNm['rest #'] = np.nan

# 筛选source为HR的行
hr_mask = cntByUserNm['source'] == 'HR'

# 处理total number ≤500的情况
low_val_mask = hr_mask & (cntByUserNm['total number'] <= 500)
cntByUserNm.loc[low_val_mask, 'keep #'] = cntByUserNm.loc[low_val_mask, 'total number']
cntByUserNm.loc[low_val_mask, 'rest #'] = 0

# 处理total number >500的情况
high_val_mask = hr_mask & (cntByUserNm['total number'] > 500)
cntByUserNm.loc[high_val_mask, 'keep #'] = 500
cntByUserNm.loc[high_val_mask, 'rest #'] = cntByUserNm.loc[high_val_mask, 'total number'] - 500

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:55:21