当前位置: 首页 > 后端技术 > Python

完整的数据分析流程:Python中的Pandas如何解决业务问题

时间:2023-03-26 02:11:09 Python

开篇Python作为一门胶水般的胶水语言,几乎无所不能,在数据科学领域的作用更是无可替代。在数据分析的硬实力中,Python是一个值得学习的工具。其中,Pandas是数据分析师使用最多的模块。如果你已经接触过它,不妨走一遍完整的数据分析流程,探索一下Pandas是如何解决业务问题的。数据背景为了尽可能多地使用不同的Pandas功能,我设计了一个奇怪但真实的数据。说白了就是有很多不规范等着我们去清理。数据来源改编自超市订单,文末附上文件路径。导入所需模块importpandasaspddataimportPandas提供了丰富的数据IO接口,最常用的是pd.read_excel和pd.read_csv函数。data=pd.read_excel('文件路径.xlsx',sheet_name='页面名称')data=pd.read_csv('文件路径.csv')从超市数据集中导入多页数据:orders=pd.read_excel('SupermarketDataset.xlsx',sheet_name='OrderSheet')customers=pd.read_excel('SupermarketDataset.xlsx',sheet_name='CustomerTable')products=pd.read_excel('SupermarketDataset.xlsx',sheet_name='producttable')这个环节除了导入数据外,还需要对数据有一个初步的了解,清楚哪些字段,以及它们的定义这里我们使用pd.Series.head()查看各个数据表的字段和字段样本数据厘清业务问题和分析思路在实际业务分析中,在开始分析之前,需要明确分析目标,逆向分析方法、分析指标,然后逆向需要的数据。这就是“以终为始”的落地思维。假设业务需求是通过用户分层运营,形成差异化的用户运营策略。数据分析师经过评估认为,可以基于RFM用户价值模型对客户进行分组,根据不同族群画像的特点制定运营策略。用户是对价格敏感的忠实客户,需要通过打折刺激消费。因此,这里的分析方法是通过RFM模型对现有用户进行分组,通过统计每个分组的数据特征,为业务提供策略建议。明确了业务需求和分析方法后,我们就可以确定客户R、F、M、客单价的统计数据进行画像分析,然后就可以进入下一步了。特征工程与数据清洗数据科学中有一句话叫做“GarbageIn,GarbageOut”,意思是如果用于分析的数据质量很差,错误很多,那么无论分析模型多么精密复杂方法是,它不能改变。花来了,结果还没有。所以有一种说法,数据科学家80%的工作都在做数据预处理。特征工程主要用在机器学习算法模型的过程中。它是一个为了模型达到最佳效果的系统工程,包括数据预处理(DataPrePorcessing)、特征提取(FeatureExtraction)、特征选择(FeatureSelection)和特征构建(FeatureConstruction)等问题。说白了,可以分为两部分:数据预处理,可以理解为我们常说的数据清洗;特征构建,比如在RFM模型和群体用户画像的构建中,R、F、M、客单价等标签。对应的特征。(当然,RFM不是机器学习模型,这里为了便于理解做一下解释。)数据清洗什么是数据清洗?数据清洗是指找出数据中的“异常值”,并对其进行“处理”,使数据应用层面的结论更贴近真实业务。异常值:非标准数据,如空值、重复数据、无用字段等,需要注意是否存在不合理值,如订单数据中的内测订单、200岁以上的客户等.特别注意数据格式是否合理,否则会影响表合并报错、聚合统计报错等不符合业务分析场景的数据。比如你要分析2019-2021年的用户行为,这个时间段以外的行为就不应该纳入分析。如何处理:一般情况下,对于离群点,可以直接去掉,但是对于数据比较少,或者这个特征比较重要的时候,离群点可以有更丰富的处理方式,比如用平均值代替。理解了数据清洗的含义后,我们就可以开始使用Pandas来练习这部分内容了。数据类型首先使用pd.dtypes检查数据字段是否合理。发现订单日期和数量是Object(一般为字符)类型,后面无法用于计算。需要使用pd.Series.astype()或pd.Series.apply()方法修改字符类型orders['orderdate']=orders['orderdate'].astype('datetime64')orders['quantity']=orders['quantity'].apply(int)另外,for时间类型也可以通过pd.to_datetime进行处理:orders['orderdate']=pd.to_datetime(orders['orderdate'])修改字段名有经验的数据分析师发现字段名也有问题,订单Id存在空格不方便后续引用,需要通过pd.rename()orders=orders.rename(columns={'OrderId':'OrderID','CustomerId':'CustomerID','ProductId':'ProductID'})customers=customers.rename(columns={'CustomerId':'客户ID'})多表??连接处理好字段名和数据类型后,可以使用pd.merge将多个Form合并连接起来。onintableconnection有两种方式,一种是两个表连接使用的字段名相同,直接使用on即可,不相同则使用left_on,right_on。data=orders.merge(customers,on='客户ID',how='left')data=data.merge(products,how='left',left_on='产品ID',right_on='物料编号')removeRedundantfields对于第二种情况,结果表中会有两列同义不同名,需要使用pd.drop去除冗余字段。另外,“RowId”在这里是一个无用的字段,应该一起去掉。data.drop(['materialnumber','rowId'],axis=1,inplace=True)表结构调整:文本处理——去除不符合业务场景的数据。根据业务经验,订单表中可能存在一些用于内部测试的数据,会影响分析结论,需要找出并剔除。经与业务或运维沟通后,明确测试订单的标识为“产品名称”栏中的“测试”字样。因为是文本内容,需要通过pd.Series.str.containsdata=data[~data['productname'].str.contains('test')]时间处理-removenon-analysis来查找和移除范围数据影响消费者的因素具有时间窗递减的特点。比如你10年前买了一顶可爱的帽子,并不代表你今天还需要可爱可爱的产品,因为10年足够你经历很多变化;但如果你在10天前买了一件乡村服饰,你可以确信你仍然喜欢乡村产品,因为你喜欢的风格在短期内不会有太大变化。也就是说在用户行为分析中,行为数据具有一定的时效性,因此需要结合业务场景明确时间范围,然后使用pd.Series.between()过滤出接近满足的订单数据RFM建模分析的时间范围。data=data[data['orderdate'].between('2019-01-01','2021-08-13')]featureconstruction这个环节的目的是构建一个分析模型,也就是RFM模型和群像分析必填特征字段。数据聚合——客户消费特征首先是RFM模型中客户的消费特征:R:客户最近一次购买到分析日期(设置为2021-08-14)的距离,用于判断活跃度购买用户的状态F:客户消费频率M:客户消费金额这些是一段时间内消费数据的聚合,所以可以使用pd.groupby().agg()来实现consume_df=data.groupby('customerID').agg(累计消费金额=('销售额',sum),累计消费项目数=('数量',sum),累计消费次数=('订单日期',pd.Series.nunique),最新消费date=('orderdate',max))其中,R值比较特殊,需要借用datetime模块计算日期之间的距离fromdatetimeimportdatetimeconsume_df['dormantdays']=datetime(2021,8,14)-consume_df['最新消费日期']consume_df['睡眠天数']=consume_df['休眠天数'].map(lambdax:x.days)累计客户消费数据计算统计表:Binning处理-客单价区间划分根据前面的分析思路,RFM模型用户分组最终完成,就要统计每个族群用户的消费画像。限于篇幅,这里仅统计各民族单价的分布特征。此时,计算出客单价数据后,需要使用pd.cut对客单价进行分箱,形成价格区间。consume_df['客单价']=consume_df['累计消费金额']/consume_df['累计消费次数']consume_df['客单价范围']=pd.cut(consume_df['客单价'],bins=5)使用pd.Series.value_counts方法统计客单价区间分布:pd.cut中的bins参数为划分客单价的区间数。如果填5,则平均分为5个bin。当然还是那句话,这个需要在实践中跟业务弄清楚,或者结合业务场景来确定。RFM建模完成数据清洗和特征构建后,进入建模分析环节。Tukey'sTest异常值检测根据分析经验,异常值会极大地影响统计指标,造成较大的误差。比如说马云放在你们这个班级,班级的平均资产可以算上百亿。在这里,马云是一个异常值,需要被移除。因此,在开始计算RFM阈值之前,需要对R、F、M的值进行离群值检测。这里我们使用Turkey'sTest方法,简单来说就是通过分位数之间的操作,将超出该区间的数据标记为离群值。不清楚的同学可以上知乎搜索,这里就不说了。土耳其的测试方法依赖于分位数的计算。在Pandas中,分位数由pd.Series.quantiledefturkeys_test(fea)计算:Q3=consume_df[fea].quantile(0.75)Q1=consume_df[fea].quantile(0.25)max_=Q3+1.5*(Q3-Q1)min_=Q1-1.5*(Q3-Q1)ifmin_<0:min_=0returnmax_,min_以上代码实现了Tukey'sTest函数,其中Q3为第75个百分位,Q1为第25位。而min_和max_形成一个合理的取值区间,在这个区间之外的数据,无论是过高还是过低,都仍然是异常值。注意,因为min_是负数,消费数据不能为负数,所以增加了一个转为0的操作。接下来在RFM特征数据表中添加一个字段“是否异常”,默认值为0,然后使用Tukey'sTest函数将异常数据标记为1,最后只需要保留值为0的数据即可.consume_df['是否异常']=0forfeainrfm_features:max_,min_=turkeys_test(fea)outlet=consume_df[fea].between(min_,max_)#boolconsume_df.loc[~outlet,'是否异常']=1consume_df=consume_df[consume_df['异常']==0]聚类和第28条原则-RFM阈值计算现在可以确保建模中使用的特征有效。这时候就需要计算RFM建模的各个指标的阈值。阈值的计算一般采用聚类算法,这里不涉及机器学习算法。本质上,聚类结果通常符合第28条原则,即重要客户群体只应占20%,因此我们可以计算第80个百分位数来近似RFM模型的阈值。M_threshold=consume_df['累计消费量'].quantile(0.8)F_threshold=consume_df['累计消费次数'].quantile(0.8)R_threshold=consume_df['休眠天数'].quantile(0.2)RFM模型计算RFM阈值之后,就可以计算出客户的RFM特性。值超过阈值则为1,低于阈值则为0。R值计算逻辑相反,因为R值是休眠天数,值越大,它越不活跃。consume_df['R']=consume_df['睡眠天数'].map(lambdax:1ifxF_thresholdelse0)consume_df['M']=consume_df['累计消费金额'].map(lambdax:1ifx>M_thresholdelse0)将客户RFM特征分为1和0,即high后和low,你可以进行分组计算:'M'].apply(str)rfm_dict={'1-1-1':'重要价值用户','1-0-1':'重要开发用户','0-1-1':'重要维护用户','0-0-1':'重要留存用户','1-1-0':'普通价值用户','1-0-0':'一般开发用户','0-1-0':'一般保留用户','0-0-0':'一般保留用户'}consume_df['RFMpopulation']=consume_df['RFM'].map(lambdax:rfm_dict[x])至此,完成了RFM建模和用户群计算。分组画像完成模型分组后,需要统计每个分组的人数和客单价分布。最简单的人口比例画像分析就是使用pd.Series.value_counts统计每个族群的人数,分析相对比例。rfm_analysis=pd.DataFrame(consume_df['RFMcrowd'].value_counts()).rename(columns={'RFMcrowd':'人数'})rfm_analysis['人口比例']=(rfm_analysis['人数people']/rfm_analysis['人数'].sum()).map(lambdax:'%.2f%%'%(x*100))数据透视表各族群客单价分布涉及多维度分析,可以使用Pandas透视函数pd在.pivot_table的实现代码中,聚合函数aggfunc我使用了pd.Series.nunique方法,意思是对值进行去重。这里,就是对customerid进行去重,统计每个价格区间的客户数量。pd.pivot_table(consume_df.reset_index(),#DataFramevalues='customerID',#valueindex='RFMcrowd',#columns分类汇总='customerunitpricerange',#columnaggfunc=pd.Series.nu??nique,#聚合函数fill_value=0,#缺失值的填充margins=True,#是否启用总行/列dropna=False,#删除缺失margins_name='All'#总行/列名).sort_values(by='All',ascending=False)这样就可以得到各个族群在不同价位段的分布情况,进一步结合其他维度的画像分析形成营销策略。反转数据透视表最后做一个风骚的操作,即数据透视表是一个多维表,但是当我们要将其导入到PowerBI等工具中进行可视化分析时,需要使用pd.melt进行数据透视表的反转将它们放入一维表中。pivot_table.melt(id_vars='RFMpopulation',value_vars=['(124.359,3871.2]','(3871.2,7599.4]','(7599.4,11327.6]','(11327.6,15055.8]','(15055.8,18784.0]']).sort_values(by=['RFMpopulation','variable'],ascending=False)这样一张表格,字段名为“crowd”,“indicator”,“value”,可以在一行中呈现信息该表是一个一维表,在各民族人口统计中,是一个二维表,需要一行一列来定位信息,至此我们建立了RFM模型,分组通过Pandas进行群像分析,完成业务分析需求,受限于篇幅,本文仅演示Pandas在数据分析过程中经常使用的功能和方法,整个分析过程也很重要,如果你是对一些功能不熟悉的,鼓励学生使用知乎或搜索引擎来补充学习。同时,也欢迎加饼干哥微信讨论。更多Pandas功能使用说明,可以查询中文文档项目内容也会以实际业务实现的方式进行介绍。