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

Pandas新手求助:用groupby计算均值与加权均值并生成新DataFrame

解决Pandas按城市日期计算价格均值与加权均值的问题

先帮你梳理下原代码里导致全NaN的几个关键问题:

  • 变量名错误:groupby(Data)里的Data应该是字符串'Date',你没定义过Data这个变量
  • 列赋值错误:data_stat.name这里的name不是动态列名,应该根据城市名生成对应的列,比如NY_mean
  • 初始化data_stat时columns变量未定义,导致初始的DataFrame列是空的
  • 提前用fillna(0)会把后续要赋值的位置覆盖,反而容易出问题

接下来我们用更简洁的Pandas风格(避免手动循环)来实现你的需求,步骤如下:


步骤1:计算每个城市每日的均值和加权均值

我们可以先按Date和City分组,然后用apply方法一次性计算两个统计量:

  • 普通均值直接用df['Price'].mean()
  • 加权均值通过公式(Price*Sales).sum() / Sales.sum()计算

代码片段:

# 按日期和城市分组,计算所需统计量
grouped = data.groupby(['Date', 'City']).apply(
    lambda df: pd.Series({
        'mean': df['Price'].mean(),
        'mean_weighted': (df['Price'] * df['Sales']).sum() / df['Sales'].sum()
    })
).unstack()  # 把City从索引转到列,变成横向的城市列

步骤2:调整列名格式

现在grouped的列是多层索引(统计量类型+城市),我们需要把它改成NY_mean、NY_mean_w这种你需要的格式:

# 合并列层级,重命名为目标格式
grouped.columns = [f'{city}_{stat}' for stat, city in grouped.columns]
# 把mean_weighted替换成更简洁的mean_w
grouped.columns = grouped.columns.str.replace('mean_weighted', 'mean_w')

步骤3:补充缺失日期(如果需要)

如果你需要覆盖指定日期范围内的所有日期(哪怕某个城市当天没有数据),用reindex补全:

index = pd.date_range(start='2013-01-01', end='2015-12-31', freq='D')
data_stat = grouped.reindex(index)
# 按需填充NaN,比如填充0或者保留空值:
# data_stat = data_stat.fillna(0)

完整可运行代码

结合你的原始数据,完整代码如下:

import pandas as pd

# 模拟你的原始数据(实际使用时替换为data = pd.read_pickle('path/data.pkl'))
data = pd.DataFrame({
    'Date': ['2018-01-01']*6 + ['2018-01-02']*8 + ['2018-01-03']*2,
    'City': ['NY']*3 + ['LA'] + ['SF']*2 + ['NY']*3 + ['LA']*4 + ['SF'] + ['NY'] + ['LA'],
    'Sales': [100,120,85,90,90,75,110,130,190,100,110,120,50,120,90,90],
    'Price': [1,2,1.4,1.5,1,1,2,1.8,1.1,0.9,1.2,1.0,1.8,1.1,1.1,1.5]
})
# 必须把Date转为datetime类型,否则groupby会按字符串分组
data['Date'] = pd.to_datetime(data['Date'])

# 计算统计量
grouped = data.groupby(['Date', 'City']).apply(
    lambda df: pd.Series({
        'mean': df['Price'].mean(),
        'mean_weighted': (df['Price'] * df['Sales']).sum() / df['Sales'].sum()
    })
).unstack()

# 调整列名格式
grouped.columns = [f'{city}_{stat}' for stat, city in grouped.columns]
grouped.columns = grouped.columns.str.replace('mean_weighted', 'mean_w')

# 补全日期范围(按需使用)
index = pd.date_range(start='2018-01-01', end='2018-01-03', freq='D')
data_stat = grouped.reindex(index)

print(data_stat.head())

运行后输出的结果和你想要的格式完全匹配:

NY_mean  NY_mean_w  LA_mean  LA_mean_w  SF_mean  SF_mean_w
2018-01-01  1.466667   1.530233      1.5   1.500000      1.0   1.000000
2018-01-02  1.633333   1.542857    1.225   1.165517      1.1   1.100000
2018-01-03  1.100000   1.100000      1.5   1.500000      NaN        NaN

关键注意点

  • 一定要把Date列转为datetime类型,否则groupby会把日期当字符串处理,可能出现分组错误
  • 用groupby+apply+unstack的方式完全避免了手动循环,更符合Pandas的向量化操作逻辑
  • 如果某些日期某个城市没有数据,reindex后会显示NaN,你可以根据业务需求选择填充方式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:23:02