如何计算Pandas中特定年份创建文档的timespan列总和?
解决特定年份timespan总和计算返回0的问题
看起来你遇到的问题主要来自两个潜在的点:意外修改原始DataFrame的列,或者**timespan列的解析逻辑存在问题**。下面一步步帮你排查和解决:
1. 核心问题:不要修改全局的creation列
你的time函数里直接执行了my_ocan['creation'] = pd.DatetimeIndex(my_ocan['creation']).year,这会把原始DataFrame中creation列的datetime类型直接替换成整数年份。不仅会污染原始数据,还可能导致后续多次调用函数时出现逻辑混乱(比如第二次调用时,creation已经是整数,再用DatetimeIndex处理会出错)。
更稳妥的做法是不修改原始列,而是在筛选时动态提取年份:
def do_get_citations_per_year(year): # 直接通过dt.year提取年份进行筛选,不修改原始DataFrame filtered_data = my_ocan[my_ocan['creation'].dt.year == year] doc_count = len(filtered_data) # 计算timespan总和 total_timespan = filtered_data['timespan'].sum() # 计算平均timespan(处理除数为0的情况) avg_timespan = total_timespan / doc_count if doc_count > 0 else 0 return (doc_count, avg_timespan)
2. 检查timespan的解析逻辑
你提到timespan最终是int64类型,但如果你的parse函数没有正确解析原始的周期字符串(比如示例中的P2Y),就会导致所有timespan值为0,自然求和结果也是0。
比如针对P2Y这类ISO 8601周期格式,你可以这样写parse函数:
def parse(period_str): # 提取周期字符串中的数字部分 if not period_str or not isinstance(period_str, str): return 0 # 过滤出所有数字字符并转换为整数 num_part = ''.join([c for c in period_str if c.isdigit()]) return int(num_part) if num_part else 0
测试一下这个函数:parse("P2Y")会返回2,这样timespan列就会有有效数值,求和也能得到正确结果。
3. 优化建议:避免使用全局变量
全局变量my_ocan容易导致数据被意外修改,建议把处理后的DataFrame作为参数传递给统计函数,让代码更健壮:
def do_process_citation_data(f_path): my_ocan = pd.read_csv(f_path, names=['oci', 'citing', 'cited', 'creation', 'timespan', 'journal_sc', 'author_sc'], parse_dates=['creation', 'timespan']) my_ocan = my_ocan.iloc[1:] # 移除表头行 my_ocan['creation'] = pd.to_datetime(my_ocan['creation'], format="%Y-%m-%d", yearfirst=True) my_ocan['timespan'] = my_ocan['timespan'].apply(parse) return my_ocan def do_get_citations_per_year(df, year): filtered_data = df[df['creation'].dt.year == year] doc_count = len(filtered_data) total_timespan = filtered_data['timespan'].sum() avg_timespan = total_timespan / doc_count if doc_count > 0 else 0 return (doc_count, avg_timespan) # 使用示例 processed_df = do_process_citation_data("citations.csv") year_1985_stats = do_get_citations_per_year(processed_df, 1985) print(f"1985年文档数:{year_1985_stats[0]},平均timespan:{year_1985_stats[1]}")
这样修改后,既保护了原始数据,也让函数的复用性更强。
内容的提问来源于stack exchange,提问作者Lisa Siurina
相关产品推荐
相关产品推荐

