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

Pandas使用update合并DataFrame返回None,致to_csv报错的解决方法

问题解决:DataFrame.update导致NoneType错误

问题描述

合并足球赛事数据的archive和df_new两个DataFrame时,执行df_merge = df_merge.update(df_results)后,df_merge变为NoneType,调用to_csv时触发如下错误:

AttributeError: 'NoneType' object has no attribute 'to_csv'

核心原因

Pandas的DataFrame.update()方法是原地修改当前DataFrame,不会返回新的DataFrame对象,它的返回值是None。把这个返回值赋值给df_merge,会直接覆盖原有的DataFrame对象,导致后续调用to_csv时出错。

解决方案

1. 修正update的调用方式

删除赋值操作,直接原地修改:

# 错误写法:df_merge = df_merge.update(df_results)
df_merge.update(df_results)  # 正确写法,原地修改,不返回新对象

2. 优化合并逻辑(可选)

原合并代码存在冗余,可简化为基于唯一标识的合并逻辑,确保数据匹配更准确:

# 替换原合并代码
df_merge = df_csv.merge(dt, on=['match_date', 'competition', 'team_home', 'team_away', 'match'], how='left')
# 合并后处理列名冲突,优先保留新数据填充原空值
for col in ['home_goals', 'away_goals', 'score']:
    df_merge[col] = df_merge[f'{col}_y'].fillna(df_merge[f'{col}_x'])
# 保留原csv的列顺序
df_merge = df_merge[df_csv.columns]

3. 修复数据类型潜在问题

get_result中直接转换int(x['home_goals'])可能因NaN报错,先处理空值:

def get_result(df):
    df = df[(df['score'].notnull()) & (df['result'].isnull())].copy()  # 加copy避免SettingWithCopyWarning
    # 先填充空值为0,再转int
    df['home_goals'] = df['home_goals'].fillna(0).astype(int)
    df['away_goals'] = df['away_goals'].fillna(0).astype(int)
    df['result'] = df.apply(lambda x: market_result(x['team_home'], x['team_away'], x['tip'], x['home_goals'], x['away_goals']), axis=1)
    return df

修改后的完整代码

import pandas as pd

def market_result(home,away,mkt,hg,ag):
    if (mkt == f'{home} To Win') and (hg > ag):
        return 'GREEN'
    if (mkt == f'{home} To Win') and (hg <= ag):
        return 'RED'
    if (mkt == f'{away} To Win') and (ag > hg):
        return 'GREEN'
    if (mkt == f'{away} To Win') and (ag <= hg):
        return 'RED'
    if (mkt == 'Both Teams To Score') and (hg > 0) and (ag > 0):
        return 'GREEN'
    if (mkt == 'Both Teams To Score') and ((hg == 0) or (ag == 0)):
        return 'RED'
    if (mkt == 'Both Teams To Score - No') and ((hg == 0) or (ag == 0)):
        return 'GREEN'
    if (mkt == 'Both Teams To Score - No') and ((hg > 0) or (ag > 0)):
        return 'RED'
    if (mkt == 'Under 2.5 Goals') and (hg+ag < 2.5):
        return 'GREEN'
    if (mkt == 'Under 2.5 Goals') and (hg+ag >= 2.5):
        return 'RED'
    if (mkt == 'Over 2.5 Goals') and (hg+ag > 2.5):
        return 'GREEN'
    if (mkt == 'Over 2.5 Goals') and (hg+ag <= 2.5):
        return 'RED'
    if (mkt == 'Under 3.5 Goals') and (hg+ag < 3.5):
        return 'GREEN'
    if (mkt == 'Under 3.5 Goals') and (hg+ag >= 3.5):
        return 'RED'
    if (mkt == 'Over 3.5 Goals') and (hg+ag > 3.5):
        return 'GREEN'
    if (mkt == 'Over 3.5 Goals') and (hg+ag <= 3.5):
        return 'RED'

def get_result(df):
    df = df[(df['score'].notnull()) & (df['result'].isnull())].copy()
    df['home_goals'] = df['home_goals'].fillna(0).astype(int)
    df['away_goals'] = df['away_goals'].fillna(0).astype(int)
    df['result'] = df.apply(lambda x: market_result(x['team_home'], x['team_away'], x['tip'], x['home_goals'], x['away_goals']), axis=1)
    return df

def append_matches(archive,df_new):
    df_csv = pd.read_csv(archive)
    # 处理空字符串为NaN
    df_csv = df_csv.replace('', pd.NA)
    dt = pd.read_csv(df_new)
    
    # 简化合并逻辑
    df_merge = df_csv.merge(dt, on=['match_date', 'competition', 'team_home', 'team_away', 'match'], how='left')
    # 合并后填充数据
    for col in ['home_goals', 'away_goals', 'score']:
        df_merge[col] = df_merge[f'{col}_y'].fillna(df_merge[f'{col}_x'])
    # 保留原csv的列顺序
    df_merge = df_merge[df_csv.columns]
    
    df_results = get_result(df_merge)
    # 直接原地更新,不赋值
    df_merge.update(df_results)
    df_merge.to_csv(archive, index=False)

def main():
    append_matches('archive.csv','df_new.csv')

if __name__ == '__main__':
    main()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 02:50:35