使用iloc和loc赋值结果不同,如何消除SettingToCopyWarning并保留iloc功能?
解决SettingWithCopyWarning并保留iloc原有功能的方法
问题根源
df.iloc[idx]['labels']触发警告:因为iloc[idx]返回的是原DataFrame的视图,直接修改视图会让pandas无法确认你是否要修改原数据,因此抛出SettingWithCopyWarning。- 改用
loc[idx, 'labels']后行数增加:你的DataFrame索引并非连续的0起始整数(比如存在重复索引、非整数索引),loc是按标签匹配,当idx这个标签不存在时,pandas会自动新增一行,导致行数从16280变成16751。
直接解决方案
使用iloc的位置赋值语法,同时指定列的位置,直接修改原DataFrame,既消除警告又不会新增行:
方案1:循环内直接获取列位置
for idx, row in enumerate(df.to_dict('records')): instances = row['instances'] labels = row['labels'].split('|') for instance in instances: if instance not in relevant_labels: labels = ['O' if instance in l else l for l in labels] # 修改为iloc的位置赋值 df.iloc[idx, df.columns.get_loc('labels')] = '|'.join(labels)
方案2:提前获取列位置(更高效)
# 循环外预先获取labels列的位置索引 labels_col_idx = df.columns.get_loc('labels') for idx, row in enumerate(df.to_dict('records')): instances = row['instances'] labels = row['labels'].split('|') for instance in instances: if instance not in relevant_labels: labels = ['O' if instance in l else l for l in labels] df.iloc[idx, labels_col_idx] = '|'.join(labels)
优化建议(更高效的写法)
遍历16k行的循环效率较低,推荐用apply方法替代,代码更简洁且无警告:
def process_single_row(row): instances = row['instances'] labels = row['labels'].split('|') for instance in instances: if instance not in relevant_labels: labels = ['O' if instance in l else l for l in labels] return '|'.join(labels) df['labels'] = df.apply(process_single_row, axis=1)
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

