Python Pandas函数参数传递报错求助:active_target调用异常
active() Result to active_target() Let's break down your problem step by step, fix the hidden bugs in your original functions, and get your active_target working exactly how you want it.
First, Fix the active() Function
Your original active function has two critical bugs that would cause errors before we even get to active_target:
- You used
groupby('customer_id')but your DataFrame’s column is namedcust_id - After grouping to get the max order date, you lose the
Frequencycolumn, so the final filter onFrequency >= freqwon’t work at all.
Here’s the corrected, functional version:
import pandas as pd import datetime # Your original DataFrame df = pd.DataFrame({ 'cust_id': [1,1,2,2,1,3,3,4,4,3,3,3], 'order_date': [ '2015-01-16', '2019-12-03', '2014-12-21', '2015-01-10', '2015-01-10', '2018-01-18', '2017-03-04', '2019-11-05', '2010-01-01', '2019-12-06', '2002-01-01', '2018-01-01' ] }) df['order_date'] = pd.to_datetime(df['order_date']) def active(month_before_current_month, freq): # Calculate frequency per customer (use transform to keep all rows) df['Frequency'] = df.groupby('cust_id')['order_date'].transform('nunique') # Get most recent order date per customer recent_customers = df.groupby('cust_id')['order_date'].max().reset_index().rename(columns={'order_date': 'Most_recent_date'}) # Merge back the frequency data we calculated earlier recent_customers = recent_customers.merge(df[['cust_id', 'Frequency']].drop_duplicates(), on='cust_id') # Calculate the cutoff date for "recent" transactions cutoff_date = datetime.date.today() - datetime.timedelta(days=month_before_current_month*365//12) # Filter customers who meet both criteria result = recent_customers[ (recent_customers['Most_recent_date'].dt.date >= cutoff_date) & (recent_customers['Frequency'] >= freq) ] return result
Calling active(1, 3) will now return your expected output correctly:
cust_id Most_recent_date Frequency 0 1 2019-12-03 3 1 3 2019-12-06 5
Why Your Modified active_target() Throws an Error
Your revised active_target uses **kwargs, which tells Python the function only accepts keyword arguments (like key=value pairs). But when you call active_target(active(1,3)), you’re passing a positional argument (the DataFrame returned by active()), which doesn’t match the function’s signature. That’s exactly what the error TypeError: active_target() takes 0 positional arguments but 1 was given means.
Two Fixes for active_target()
Fix 1: Directly Accept the active() Result (Simplest)
If your main goal is to pass the output of active() directly to active_target, just define the function to accept a DataFrame parameter explicitly:
def active_target(active_df): return active_df['Frequency'].mean() # Call it like this: active_target(active(1, 3)) # Returns (3+5)/2 = 4.0
Fix 2: Support Both Passing Parameters and Precomputed Data
If you want flexibility (either pass parameters to let active_target run active() internally, or pass a precomputed DataFrame), adjust the function to handle both cases:
def active_target(**kwargs): # Check if we're given a precomputed active DataFrame if 'active_df' in kwargs: df = kwargs['active_df'] else: # Extract parameters to run active() internally try: month = kwargs['month_before_current_month'] freq = kwargs['freq'] df = active(month, freq) except KeyError: raise ValueError("Either pass 'active_df' or both 'month_before_current_month' and 'freq'") return df['Frequency'].mean() # Both calls work: # 1. Pass precomputed data active_target(active_df=active(1, 3)) # 2. Pass parameters to compute internally active_target(month_before_current_month=1, freq=3)
Quick Notes
- Always double-check column names when grouping/merging—small typos like
customer_idvscust_idare easy to miss but break everything. **kwargsis for keyword arguments only, not positional ones. If you want to accept arbitrary positional arguments, use*args, but in this case, an explicit parameter for the DataFrame is cleaner and more readable.
内容的提问来源于stack exchange,提问作者noob




