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

如何在Pandas多索引DataFrame中筛选符合季度数据要求的设施并汇总花费

问题描述

我有一个以日期(月份)和FacilityID为多索引的Pandas DataFrame,包含每个设施的TotalSpend字段。需要汇总满足以下条件的设施的TotalSpend:

  • 该设施在当前季度的三个月均有数据
  • 该设施在上一年同季度的三个月也均有数据

尝试提取4、5、6月的子集并内连接时,报错提示对象不是DataFrame。希望筛选出在季度所有三个月都有数据的FacilityID,仅保留这些数据。

期望输出:汇总2024年Q2所有符合条件的设施的花费总和,以及2023年Q2这些相同设施的花费总和。示例中仅Facility 1符合要求,2024年Q2总和为450,2023年Q2总和为300。

当前问题代码:

import pandas as pd
import datetime

def open_file(path, quarter_number, months):
    df_raw = pd.DataFrame({'Date':["2024-04-01","2024-05-01","2024-06-01", "2024-06-01","2024-05-01","2023-04-01","2023-05-01","2023-06-01","2024-05-01","2024-06-01","2023-05-01","2023-06-01", "2023-04-01","2024-05-01","2024-06-01"],
                         'FacilityID': [1,1,1,1,1,1,1,1,2,2,2,2,3,4,4],
                         'TotalSpend': [100,110,120,50,70,90,100,110,150,140,120,60,90,190,150]
    }).set_index('Date')
    df = df_raw.groupby(['Date', 'FacilityID'])['TotalSpend'].sum()
    # print(df)

    cur_dates = []
    prev_dates = []

    for month in months:
        cur_date = datetime.date(2024, month, 1)
        prev_date = datetime.date(cur_date.year - 1, month, 1)
        cur_dates.append(cur_date.strftime('%Y-%m-%d'))
        prev_dates.append(prev_date.strftime('%Y-%m-%d'))

    #this is where i'm having issues
    cur_data =df.loc[[cur_dates[1]]].join(df.loc[[cur_dates[1]]], on='FacilityID' ,join = "inner")
    prev_data = df.loc[prev_dates[0]:prev_dates[-1]]

    # print(cur_data)
    # print(prev_data)

if __name__ == "__main__":
    change = open_file("path",2 ,[4,5,6])
    print(change)
解决方案

问题核心是筛选出连续两个季度都完整拥有三个月数据的设施,原代码错误在于groupby后得到的是Series而非DataFrame,导致join操作失败。以下是修正后的实现:

步骤1:修正数据结构

groupby后添加.reset_index(),让结果保持DataFrame格式,方便后续操作:

df = df_raw.groupby(['Date', 'FacilityID'])['TotalSpend'].sum().reset_index()

步骤2:提取目标季度数据

从日期中解析年份和月份,快速筛选当前季度与上年同季度的数据:

# 解析年份和月份
df['Year'] = pd.to_datetime(df['Date']).dt.year
df['Month'] = pd.to_datetime(df['Date']).dt.month

# 定义目标季度
cur_year, target_months = 2024, [4,5,6]
prev_year = cur_year - 1

# 筛选两个季度的数据子集
cur_q_data = df[(df['Year'] == cur_year) & (df['Month'].isin(target_months))]
prev_q_data = df[(df['Year'] == prev_year) & (df['Month'].isin(target_months))]

步骤3:筛选符合条件的设施

对每个季度的数据按FacilityID分组,统计每个设施的月份覆盖数,保留覆盖完整三个月的设施:

# 当前季度符合条件的设施
valid_cur_fac = cur_q_data.groupby('FacilityID')['Month'].nunique()
valid_cur_fac = valid_cur_fac[valid_cur_fac == 3].index.tolist()

# 上年同季度符合条件的设施
valid_prev_fac = prev_q_data.groupby('FacilityID')['Month'].nunique()
valid_prev_fac = valid_prev_fac[valid_prev_fac == 3].index.tolist()

# 取两者交集,即两个季度都满足条件的设施
final_valid_fac = list(set(valid_cur_fac) & set(valid_prev_fac))

步骤4:计算总花费

用筛选后的设施列表,分别计算两个季度的总花费:

cur_total = cur_q_data[cur_q_data['FacilityID'].isin(final_valid_fac)]['TotalSpend'].sum()
prev_total = prev_q_data[prev_q_data['FacilityID'].isin(final_valid_fac)]['TotalSpend'].sum()

完整修正代码

import pandas as pd
import datetime

def open_file(path, quarter_number, months):
    df_raw = pd.DataFrame({'Date':["2024-04-01","2024-05-01","2024-06-01", "2024-06-01","2024-05-01","2023-04-01","2023-05-01","2023-06-01","2024-05-01","2024-06-01","2023-05-01","2023-06-01", "2023-04-01","2024-05-01","2024-06-01"],
                         'FacilityID': [1,1,1,1,1,1,1,1,2,2,2,2,3,4,4],
                         'TotalSpend': [100,110,120,50,70,90,100,110,150,140,120,60,90,190,150]
    }).set_index('Date').reset_index()
    
    # 按日期和设施分组求和,转为DataFrame
    df = df_raw.groupby(['Date', 'FacilityID'])['TotalSpend'].sum().reset_index()
    
    # 解析年份和月份
    df['Year'] = pd.to_datetime(df['Date']).dt.year
    df['Month'] = pd.to_datetime(df['Date']).dt.month
    
    cur_year = 2024
    prev_year = cur_year -1
    
    # 筛选两个季度的数据
    cur_q_data = df[(df['Year'] == cur_year) & (df['Month'].isin(months))]
    prev_q_data = df[(df['Year'] == prev_year) & (df['Month'].isin(months))]
    
    # 筛选季度内三个月全有数据的设施
    valid_cur = cur_q_data.groupby('FacilityID')['Month'].nunique() == 3
    valid_cur_fac = valid_cur[valid_cur].index.tolist()
    
    valid_prev = prev_q_data.groupby('FacilityID')['Month'].nunique() ==3
    valid_prev_fac = valid_prev[valid_prev].index.tolist()
    
    # 取交集
    final_fac = list(set(valid_cur_fac) & set(valid_prev_fac))
    
    # 计算总和
    cur_total = cur_q_data[cur_q_data['FacilityID'].isin(final_fac)]['TotalSpend'].sum()
    prev_total = prev_q_data[prev_q_data['FacilityID'].isin(final_fac)]['TotalSpend'].sum()
    
    return {'2024Q2总花费': cur_total, '2023Q2总花费': prev_total}

if __name__ == "__main__":
    result = open_file("path",2 ,[4,5,6])
    print(result)

运行结果:

{'2024Q2总花费': 450, '2023Q2总花费': 300}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:24:57