【问题标题】:Specific aggregations for data in weekly timeframes in Python (Pandas)Python(Pandas)中每周时间范围内数据的特定聚合
【发布时间】:2021-03-11 07:42:29
【问题描述】:

我目前正在解决一个问题,我在试图找出解决方案的最佳方法时遇到了困难,也许你们可以帮助我。

我有一个包含来自客户关系呼叫中心的呼叫的数据集,我需要以特定方式对其进行汇总。该公司正在调查新客户的行为,他们认为新客户往往比老客户更频繁地打电话(这是意料之中的,但我需要使其可视化)。所以我需要从某个时期进入公司的客户那里知道,呼叫中心在同一时期和以后的时期接到了多少新客户的电话。

基本上,来自第 1 周订阅的客户,有多少人在第 1 周致电,有多少人在第 2 周致电,等等。

以下是数据集的预览:

date_ref 是通话日期。 cred_date 是订阅日期。

我遇到了一个在 pandas 中使用布尔索引的解决方案,而且,男孩,代码看起来很丑吗!我也不太相信这是否可靠。这是我到目前为止所做的:

# Aggregation functions to be passed to groupby
aggregation = {
    'n_creds': ('account_id', pd.Series.nunique),
    'n_calls': ('date_ref', 'count')
}

# Groupby splitting dates in weeks and with specified aggregations
mcases_agg = mcases_ready.groupby(pd.Grouper(key = 'cred_date', freq = 'W')).agg(**aggregation)
mcases_idx_list = mcases_agg.index.tolist()

n_calls_list = []
for i, _ in enumerate(mcases_idx_list):
    if i == 0:
        df = mcases[mcases['cred_date'] <= mcases_idx_list[i]]
        n_calls_from_cred_this_week = df[(df['date_ref'] >= mcases_idx_list[i]) & \  
                                         (df['date_ref'] < (mcases_idx_list[i + 1]))]['account_id'].nunique()
        n_calls_list.append(n_calls_from_cred_this_week)
    
    elif i != len(mcases_idx_list) - 1:
        df = mcases[mcases['cred_date'] <= mcases_idx_list[i]]
        n_calls_from_cred_this_week = df[(df['date_ref'] >= mcases_idx_list[i]) & \ 
                                         (df['date_ref'] < (mcases_idx_list[i + 1]))]['account_id'].nunique()
        n_calls_list.append(n_calls_from_cred_this_week)
    
    else:    
        df = mcases[mcases['cred_date'] <= mcases_idx_list[i]]
        n_calls_from_cred_this_week = df[(df['date_ref'] >= mcases_idx_list[i])]['account_id'].nunique()
        n_calls_list.append(n_calls_from_cred_this_week)

我想听听社区的意见,你们是否遇到过类似的问题以及您是如何解决的,如果还没有,请分享您对实现更直接的代码的建议使用一些我不熟悉的工具。

谢谢!

【问题讨论】:

    标签: python datetime data-science aggregation


    【解决方案1】:

    在我有点头疼之后,我为我的问题找到了一个更好的解决方案(证明疲惫的大脑资源有限)。

    1. 首先,我计算了每次通话 (date_ref) 和订阅日期 (cred_date) 之间的天数,并将其保存到新列 interval_cred_call

      mcases['interval_cred_call'] = (mcases['date_ref'] - mcases['cred_date']).dt.days

    2. 根据这个值,我为每周时间的垃圾邮件创建了特定列,如果呼叫时间 bools 并保存到列 Week #1,然后在 7 到 14 天之间并将其保存到Week #2 列,依此类推...

    3. 然后,我使用函数自动执行任务迭代,这可能会导致 pd.DataFrame 或水平条形图。

    下面是我编写的函数:

    def n_call_timewindow(df, n_days = 100, plot = False):
        '''
        This function calculates the number of calls (cases) after n_days // 7 entrance in the cred database and returns a pd.DataFrame with columns being the weeks ahead of entrance.
        
        Parameters:
     
        ** n_days: 
        Number of days to be included in the analysis. Please observe that the output will be in weeks, therefore the number of days will be divided by 7, and remainders will be discarded.
        
        ** plot (default, False)
        If set to True, will plot a horizontal bar chat instead of showing a pd.DataFrame.\n
        ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        '''
        df = df.copy()
        
        week = n_days // 7
        for i in range(0, week + 1):
            if i == 0:
                df[f'Semana #{i + 1}'] = (df['interval_cred_call'] <= (i + 7)).astype(int)
            else:
                df[f'Semana #{i + 1}'] = ((df['interval_cred_call'] > (i * 7)) & 
                                                 (df['interval_cred_call'] <= ((i + 1) * 7))).astype(int)
    
        
        df = df.iloc[:, -(week + 1):-1]
        
        if plot == True:
            fig, ax = plt.subplots(1, figsize = (15, 5))
            fig.suptitle('Total de chamados realizados após Credenciamento\n(por semana, a partir da entrada na base)',
                         fontsize = 20, color = 'darkgreen')
            fig.tight_layout()
            df.sum().plot(kind = 'barh', alpha = .8, width = .8, color = 'limegreen', zorder = 2).invert_yaxis()
            ax.grid(b = True, axis = 'x', alpha = .2, zorder = 1)
            ax.tick_params(axis='both', colors='gray', labelsize = 14, labelcolor = 'dimgray')
            ax.spines['left'].set_color('lightgray')
            ax.spines['bottom'].set_visible(False)
            ax.spines['top'].set_visible(False)
            ax.spines['right'].set_visible(False)
            
            return f'{fig}'
    
        return df
    

    在设置参数plot = True时,结果如下:

    【讨论】:

      猜你喜欢
      • 2021-06-16
      • 2012-09-18
      • 1970-01-01
      • 1970-01-01
      • 2020-12-18
      • 2020-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多