繁体   English   中英

Python (Pandas) 中每周时间范围内数据的特定聚合

[英]Specific aggregations for data in weekly timeframes in Python (Pandas)

我目前正在解决一个问题,我无法找出提出解决方案的最佳方法,也许你们可以帮助我。

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

基本上,从第 1 周订阅的客户那里,有多少人在第 1 周打电话,有多少人在第 2 周打电话,等等。

这是数据集的先睹为快:

数据集的基础知识

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

我遇到了一个使用 boolean 索引和 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)

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

谢谢!

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

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

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

  2. 根据这个值,我为每周时间的垃圾邮件创建了特定的列,如果调用小于 7 天,则将它们分类为布尔值并保存到列Week #1 ,然后在 7 到 14 天之间并将其保存到列Week #2 ,等等……

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

下面是我编码的 function:

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时,结果如下:

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM