如何适配Pandas DataFrame的sum函数以支持可选条件参数?
The core issue with your original function is that it strictly checks for equality even when you pass an empty string—since none of your DataFrame rows have empty values for Fund, Account, or Analysis, those filters return no matches. To fix this, we need to skip the filter for any parameter that's passed as an empty string.
Here's the revised function:
import pandas as pd df = pd.DataFrame( [ ['02-09-2019',20190902, 20.00, 'F1','B1','I2'], ['23-09-2019',20190923, 237.36, 'F1','B1','I1'], ['15-11-2019',20191115, 200.00, 'F1','B1','I1'], ['16-11-2019',20191116, 2045.00, 'F1','B1','I2'], ['05-05-2020',20200505, 205.00, 'F2','B2','I1'], ], columns= ['Datestr','Datenum','Cost','Fund','Account','Analysis']) def per_sum(startdate, enddate, fund='', account='', analysis=''): # Start with date filter (always required) mask = (df.Datenum > startdate) & (df.Datenum < enddate) # Add fund filter only if parameter is non-empty if fund: mask &= (df.Fund == fund) # Add account filter only if parameter is non-empty if account: mask &= (df.Account == account) # Add analysis filter only if parameter is non-empty if analysis: mask &= (df.Analysis == analysis) return df[mask].Cost.sum()
How It Works
- We begin with the mandatory date range filter.
- For each optional parameter (
fund,account,analysis), we only apply the equality check if the parameter is a non-empty string. Empty parameters skip their respective filters entirely, allowing the function to aggregate across all values in that column.
Test Cases
Let’s verify with your example and other common scenarios:
Sum all I2 entries in 2019:
per_sum(20190000,20200000,'','','I2') # Returns 20.00 + 2045.00 = 2065.0Original working case (F1, B1, I1 in 2019):
per_sum(20190000,20200000,'F1','B1','I1') # Returns 237.36 + 200.00 = 437.36Sum all F1 entries in 2019 (any account/analysis):
per_sum(20190000,20200000,'F1','','') # Returns 20 + 237.36 + 200 + 2045 = 2502.36Sum all I1 entries across all funds/accounts and dates:
per_sum(0,99999999,'','','I1') # Returns 237.36 + 200 + 205 = 642.36
This approach keeps the function flexible for partial filtering while maintaining full compatibility with your original use case.
内容的提问来源于stack exchange,提问作者tedioustortoise

