Pandas按行条件生成Outstanding列问题求助
解决Pandas逐行条件赋值问题
问题背景
现有如下DataFrame:
| Repository | Age |
|---|---|
| DMZ Linux | 65 days |
| Linux | 3 days |
| Windows | 95 days |
需要新增Outstanding列,满足以下条件:
- 若Repository包含'DMZ'且Age>60天,赋值'True'
- 若Repository包含'DMZ'且Age<60天,赋值'False'
- 若Repository不包含'DMZ'且Age>90天,赋值'True'
- 若Repository不包含'DMZ'且Age<90天,赋值'False'
当前使用for循环处理时,所有行的Outstanding都被最后一行的结果覆盖,得到错误结果:
| Repository | Age | Outstanding |
|---|---|---|
| DMZ Linux | 65 days | True |
| Linux | 3 days | True |
| Windows | 95 days | True |
预期结果:
| Repository | Age | Outstanding |
|---|---|---|
| DMZ Linux | 65 days | True |
| Linux | 3 days | False |
| Windows | 95 days | True |
错误代码片段:
for i in range(len(report_data)): line = report_data.loc[i] if str(line['Age'] != ''): new_val = str(line['Age']).replace('days', '') no_space = new_val.replace('', '') int_val = int(no_space) if int_val > 60 and 'DMZ' in line['Repository']: report_data['Outstanding']: line['Outstanding'] = 'True' elif int_val > 90 and 'DMZ' not in line['Repository']: report_data['Outstanding']: line['Outstanding'] = 'True' else: report_data['Outstanding']: line['Outstanding'] = 'False'
错误原因
- 整列赋值而非单行:代码中
report_data['Outstanding'] = ...是对整个列赋值,每次循环都会覆盖之前所有行的结果,最终整列都是最后一行的判断结果。 - 语法错误:
report_data['Outstanding']: line['Outstanding'] = 'True'是无效语法,正确的单行赋值应该用loc指定行和列。 - Age处理错误:
new_val.replace('', '')无法去除空格,应该用strip()来清理字符串。
解决方案
方法1:修复for循环(适合新手理解)
先初始化Outstanding列,循环时用loc[i, 'Outstanding']指定单行赋值,同时修正Age的解析逻辑:
# 初始化Outstanding列 report_data['Outstanding'] = '' for i in range(len(report_data)): line = report_data.loc[i] age_str = str(line['Age']).strip() if age_str: # 提取Age的数值部分 int_val = int(age_str.replace('days', '').strip()) repo = line['Repository'] if 'DMZ' in repo: report_data.loc[i, 'Outstanding'] = 'True' if int_val > 60 else 'False' else: report_data.loc[i, 'Outstanding'] = 'True' if int_val > 90 else 'False'
方法2:使用apply逐行处理(更简洁)
定义一个处理单行的函数,通过apply(axis=1)逐行调用:
def determine_outstanding(row): age_str = str(row['Age']).strip() if not age_str: return '' int_val = int(age_str.replace('days', '').strip()) repo = row['Repository'] if 'DMZ' in repo: return 'True' if int_val > 60 else 'False' else: return 'True' if int_val > 90 else 'False' # 新增列 report_data['Outstanding'] = report_data.apply(determine_outstanding, axis=1)
方法3:向量化操作(Pandas推荐,效率最高)
先将Age转换为数值列,再用布尔索引组合条件,避免循环:
# 先提取Age的数值,生成新列 report_data['Age_Num'] = report_data['Age'].str.replace('days', '').str.strip().astype(int) # 组合条件赋值 report_data['Outstanding'] = 'False' # 条件1:含DMZ且Age>60 mask1 = (report_data['Repository'].str.contains('DMZ')) & (report_data['Age_Num'] > 60) # 条件2:不含DMZ且Age>90 mask2 = (~report_data['Repository'].str.contains('DMZ')) & (report_data['Age_Num'] > 90) # 满足任一条件则设为True report_data.loc[mask1 | mask2, 'Outstanding'] = 'True' # 可选:删除临时的Age_Num列 # report_data.drop('Age_Num', axis=1, inplace=True)
验证结果
执行上述任一方法后,都能得到预期的DataFrame:
| Repository | Age | Outstanding |
|---|---|---|
| DMZ Linux | 65 days | True |
| Linux | 3 days | False |
| Windows | 95 days | True |
内容的提问来源于stack exchange,提问作者Gailaloo
相关产品推荐
相关产品推荐

