如何基于条件从旧DataFrame创建新DataFrame并解决遍历报错
报错原因
首先明确报错的直接诱因:
- 代码中
rows = df.loc[dc-1]取到的是旧DataFrame第一行的Series对象,rows.id是该行id字段的具体数值(类型为numpy.int64),不属于可迭代对象,直接用for x in rows.id遍历必然触发类型错误。 - 除此之外原有代码还存在多处逻辑错误:未正确初始化结构匹配的新DataFrame、字段名拼写错误(原表字段是
name不是names)、索引遍历逻辑混乱、直接修改pandas对象容易触发链式赋值警告。
正确实现方案
推荐优先使用pandas分组聚合方案,逻辑简洁执行效率高,完全匹配需求规则:
import psycopg2 import pandas as pd # 数据库读取逻辑保持不变 conn = psycopg2.connect(host="<db_IP>",port=<DB_port>,dbname="dbname",user="postgres",password="Start123") df = pd.read_sql('SELECT * FROM money_account;', conn) conn.close() # 自定义分组合并逻辑,完全匹配需求 def merge_name_group(group): # 同name所有行的balance总和就是最终的balance值 total_balance = group['balance'].sum() # 优先取同组最后一个deleted=-1的行作为基准行,没有则取第一行 deleted_rows = group[group['deleted'] == -1] base_row = deleted_rows.iloc[-1].copy() if not deleted_rows.empty else group.iloc[0].copy() # 替换balance为总和 base_row['balance'] = total_balance return base_row # 按name分组聚合得到最终结果 new_df = df.groupby('name', as_index=False).apply(merge_name_group).reset_index(drop=True) print(new_df)
如果需要和需求规则逐行对应的循环实现(仅适合小数据量场景),可以用以下代码:
# 逐行循环实现(小数据量可用) new_df = pd.DataFrame(columns=df.columns) for _, old_row in df.iterrows(): current_name = old_row['name'] # 检查name是否已存在于新表 exist_index = new_df[new_df['name'] == current_name].index if len(exist_index) == 0: # 不存在直接添加行 new_df = pd.concat([new_df, old_row.to_frame().T], ignore_index=True) else: target_idx = exist_index[0] if old_row['deleted'] != -1: # 非删除行直接累加balance new_df.at[target_idx, 'balance'] += old_row['balance'] else: # 删除行先暂存原有balance,替换行后再累加 temp_bal = new_df.at[target_idx, 'balance'] new_df.loc[target_idx] = old_row new_df.at[target_idx, 'balance'] += temp_bal
内容的提问来源于stack exchange,提问作者Marcelo Costa
相关产品推荐
相关产品推荐

