在Pandas DataFrame中插入求和行时如何保留列标题
嗨~我来帮你搞定这个问题!你遇到的列名丢失问题,根源在于你用了np.insert操作DataFrame的values属性——这个属性返回的是纯numpy数组,完全丢掉了原DataFrame的列名、索引这些结构信息,所以新生成的DataFrame自然就用默认的数字列名啦。
下面给你两种简单靠谱的方法,既能添加总计行,又能完美保留原列名:
方法一:用df.loc直接添加行(最直观)
这个方法直接在原DataFrame上操作,能自动继承列名,而且代码简洁。不过要注意:你原数据里的y1、y2、y3是带前导零的字符串(比如'01'),必须先转成数值类型才能正确求和,不然会变成字符串拼接(比如'010407'),这点一定要注意!
import pandas as pd import numpy as np # 还原你的原DataFrame data = { 'Name': ['Ben', 'Jane', 'Sarah'], 'y1': ['01', '04', '07'], 'y2': ['02', '05', '07'], 'y3': ['03', '06', '06'] } df = pd.DataFrame(data) # 把y列转成整数类型(如果需要保留前导零,求和后可以再转回去) df[['y1', 'y2', 'y3']] = df[['y1', 'y2', 'y3']].astype(int) # 添加总计行,行标签设为'total' df.loc['total'] = ['total', df['y1'].sum(), df['y2'].sum(), df['y3'].sum()] # 查看结果 print(df)
运行后你会看到列名完全保留,总计行也正确计算出来了。如果之后需要把y列转回带前导零的字符串,可以用df[['y1','y2','y3']] = df[['y1','y2','y3']].astype(str).str.zfill(2)。
方法二:用pd.concat拼接DataFrame
这种方法适合需要保留原DataFrame不变,生成新的带总计行的DataFrame的场景:
# 先确保y列是数值类型(同上) df[['y1', 'y2', 'y3']] = df[['y1', 'y2', 'y3']].astype(int) # 构造总计行的小DataFrame,列名和原df完全一致 total_df = pd.DataFrame({ 'Name': ['total'], 'y1': [df['y1'].sum()], 'y2': [df['y2'].sum()], 'y3': [df['y3'].sum()] }) # 把总计行放在最前面,拼接成新df df_with_total = pd.concat([total_df, df], ignore_index=True) print(df_with_total)
pd.concat会自动对齐列名,所以完全不用担心列名丢失的问题,ignore_index=True是让新df的索引重新从0开始排序,避免索引混乱。
为啥你的原代码会丢列名?
再回头说下你的原代码:np.insert(df.values, ...)生成的是一个numpy数组,当你用这个数组创建新DataFrame时,pandas不知道原列名是什么,就会默认用0、1、2、3作为列名。而且set_value这个方法已经被弃用了,现在推荐用df.at或者df.loc来修改单个值,但即使修改了,也没法恢复原来的列名,因为结构已经丢失了。
内容的提问来源于stack exchange,提问作者Alex

