样本切分器—利用python按比例均匀切分样本

背景:

运营部要对沉默用户进行电话召回,为了探索更高效的召回方式,分别进行了下述两种测试:

1、人工拨打电话

2、AI外呼平台拨打电话

(因方式2需要提前设定机器人的话术,本次测试中设定了两套销售话术,"话术A"和"话术B")

因此,我们要将用户名单分为三组,即:

1、人工组

2、AI话术A组

3、AI话术B组

分别对三组用户进行电话拨打,并在测试后考核接听率和成交率。

问题:

运营同事按时间范围圈选了一部分用户名单,发现名单中的用户在沉默之前分别来自于不同的流量渠道并且有些用户有参加过我们的某个活动,这两个属性("渠道属性"、"是否参与过活动")对本次测试的接听率和成交率都会产生较大的影响。

所以本次需要我们数据组解决的问题是:在考虑用户属性相同的前提下,如何均匀的切分成三个样本?(即,保证三个样本内的用户属性基本一致)

解决:

要解决上述问题,最简单的办法就是随机分组:

即,每个用户被等概率的随机分配到三个实验组当中。

这里我们可以使用机器学习模块中的拆分训练集和测试集的方法:

即,sklearn.model_selection 中的 train_test_split

在python中使用:

from sklearn.model_selection import train_test_split

分别设定训练集和测试集的切分比例进行切分,

train_date, test_date = train_test_split(df_date, train_size=0.5, test_size=0.5, random_state=123)

train_date:我们希望得到的训练集样本

test_date:我们希望得到的测试集样本

df_date:总样本

train_size、test_size:训练集/测试集切分比例

random_state:随机种子(设置某个数字,可保证随机种子相同时我们每次随机切分的结果也相同)

这样可以切成两份,那么三份如何切?

答案很简单,我们只需要对训练集或测试集再切分一次,就是三份了。

具体实现:

满足运营同事的三个小需求:

1、首先观察圈选总样本的用户属性构成是否满足我们的测试需要

2、将圈选总样本切成3份用户属性一样的测试样本

3、对比切分后3个样本的用户属性构成是否一致

样本:

运营同事圈选的总样本

 

 

代码:

导入模块/读取数据:

import pandas as pd
from sklearn.model_selection import train_test_split

df = pd.read_excel('圈选总样本.xlsx')

需求1代码:

按维度(一维或多维)分组对某列聚合后查看其非空数量的占比;并可重复查看

例如:以是否参加过活动为分组聚合,查看是否参加过活动的用户占比

def analysis(df):
    print(df.info())
    y = input('是否查看样本特征占比(y-查看,n-不查看):  ')
    if y == 'y':
        while True:
            re_check = 1
            while re_check == 1:
                group_columns = input('输入分组列名(若多维分组则用逗号间隔输入列名):').split(',')
                target_columns = input('输入聚合列名(若多个则用逗号间隔): ').split(',')
                for column in group_columns+target_columns:
                    if column not in list(df):
                        print('列名输入错误:{}'.format(column))
                        re_check = 1
                        break
                    else:
                        re_check = 0

            grouped = df.groupby(by=group_columns).count()

            rate_columns = []
            for target_column in target_columns:
                rate_name = 'rate_'+target_column
                rate_columns.append(rate_name)
                col_sum = grouped[target_column].sum()
                grouped[rate_name] = grouped.apply(lambda x: str(round((x[target_column]/col_sum)*100, 2))+'%', axis=1)

            print(grouped[target_columns+rate_columns])

            check_again = input('是否继续查看其他(y-查看,n-不查看): ')
            if check_again == 'y':
                continue
            else:
                break
    else:
        pass

假如,我们要查看总样本的渠道构成,那么输入和输出:

 需求2:设定比例均匀切分样本

def sample_cut(df):
    sample = df
    while True:
        n = input('输入切分样本比例(逗号间隔,例如:0.2,0.3,0.5):  ')
        sizelist = list(map(float, n.split(',')))
        if sum(sizelist) != 1:
            print('样本切分比例之和不为1')
        else:
            break
    cut_result = []
    for i in range(len(sizelist)-1):
        cut_size = sizelist[i]/sum(sizelist[i:len(sizelist)])
        cut_sample, sample = train_test_split(sample, train_size=cut_size, test_size=1.0-cut_size, random_state=123)
        cut_sample.to_excel('样本'+str(i+1)+'切分比例'+str(sizelist[i])+'数量'+str(cut_sample.shape[0])+'.xlsx', index=False)
        print('样本'+str(i+1)+' 切分比例:' + str(sizelist[i]) + '  数量:' + str(cut_sample.shape[0]))
        cut_result.append(cut_sample)
    sample.to_excel('样本'+str(len(sizelist))+'切分比例'+str(sizelist[-1])+'数量'+str(sample.shape[0])+'.xlsx', index=False)
    print('样本'+str(len(sizelist))+' 切分比例:' + str(sizelist[-1]) + '  数量:' + str(sample.shape[0]))
    cut_result.append(sample)
    return cut_result

假如我要切三份:可以输入 0.3,0.3,0.4  (注意比例之和为1)

需求3:对比验证切分后的样本是否均匀

def comparison(cut_result):
    while True:
        re_check = 1
        while re_check == 1:
            comp_cols = input('输入待对比的分组列名及聚合列名,逗号间隔(例如:is_attend,user_id): ').split(',')
            for comp_col in comp_cols:
                if comp_col not in list(cut_result[0]):
                    print('列名输入错误:{}'.format(comp_col))
                    re_check = 1
                    break
                else:
                    re_check = 0

        comp_dfs = []
        rate_columns = []
        for i in range(len(cut_result)):
            grouped = cut_result[i].groupby(by=[comp_cols[0]]).count()
            target_sum = grouped[comp_cols[1]].sum()
            rate_colname = 'rate_样本'+str(i+1)
            rate_columns.append(rate_colname)
            grouped[rate_colname] = grouped.apply(lambda x: str(round(x[comp_cols[1]]/target_sum*100, 2))+'%', axis=1)
            comp_dfs.append(grouped)
        num = 0
        for com_df in comp_dfs:
            if num == 0:
                df_temp = com_df
                num = 1
            else:
                df_temp = pd.merge(df_temp, com_df, how='left', on=comp_cols[0])
        print(df_temp[rate_columns])
        re = input('是否继续查看(y-继续,n-结束): ')

        if re != 'y':
            break
        else:
            continue

假如,验证渠道属性是否均匀

输入格式:"分组列名,聚合列名"

 

执行

#待切分样本文件路径
df = pd.read_excel('圈选总样本.xlsx')
#查看待切分样本特征占比
analysis(df)
#按设定比例随机切分成多份样本
cut_result = sample_cut(df)
#对比切分后样本特征占比
comparison(cut_result)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值