对一家全球超市四年(2011-2014)的销售数据进行 “人、货、场”分析,并给出提高销量的针对性建议。python
场:总体运营状况分析,包括销售额、销量、利润、客单价、市场布局等具体状况分析。网络
货:商品结构、优点/爆款商品、劣势/待优化商品等状况分析。app
人:客户数量、新老客户、RFM模型、复购率、回购率等用户行为分析。框架
数据来源为kaggle平台,这是一份全球大型超市四年的零售数据集,数据详尽。机器学习
数据集为 “superstore_dataset2011-2015.csv”,共有51290条数据,共24个特征。函数
1.1 加载相关库和数据集布局
使用的库主要有:pandas、numpy、matplotlib、seaborn学习
使用的数据集:
superstore_dataset2011-2015.csv优化
# 加载数据分析须要使用的库 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import warnings plt.rcParams['font.sans-serif'] = ['SimHei'] warnings.filterwarnings('ignore') # 加载零售数据集,使用'ISO-8859-1'编码方式 df = pd.read_csv('superstore_dataset2011-2015.csv',encoding='ISO-8859-1') df.head()
1.2 数据概览编码
首先看一下数据集大小(行列信息):
df.shape --------------- (51290, 24)
看一下数据概况:
# df.info() df.describe()
2.1 列名重命名
从上面发现列名不符合Python的命名规范,对列名进行一下重命名,采用下划线命名法:
df.rename(columns = lambda x: x.replace(' ', '_').replace('-', '_'), inplace=True)
看一下重命名后的列名:
df.columns ----------------- Index(['Row_ID', 'Order_ID', 'Order_Date', 'Ship_Date', 'Ship_Mode', 'Customer_ID', 'Customer_Name', 'Segment', 'City', 'State', 'Country', 'Postal_Code', 'Market', 'Region', 'Product_ID', 'Category', 'Sub_Category', 'Product_Name', 'Sales', 'Quantity', 'Discount', 'Profit', 'Shipping_Cost', 'Order_Priority'], dtype='object')
2.2 数据类型处理
查看一下各个列的数据类型:
df.dtypes ----------------- Row_ID int64 Order_ID object Order_Date object Ship_Date object Ship_Mode object Customer_ID object Customer_Name object Segment object City object State object Country object Postal_Code float64 Market object Region object Product_ID object Category object Sub_Category object Product_Name object Sales float64 Quantity int64 Discount float64 Profit float64 Shipping_Cost float64 Order_Priority object dtype: object
从上面看到,大部分为object类型,销量、销售额、利润等为数值型,不须要进行数据类型处理。下单日期应为datetime类型,须要进行处理。
df["Order_Date"] = pd.to_datetime(df["Order_Date"]) df["Order_Date"].sample(5) ---------------------------------- 9319 2013-04-10 30390 2012-03-19 31025 2013-08-19 32210 2014-03-20 43430 2012-11-26 Name: Order_Date, dtype: datetime64[ns]
为了便于分析每一年和每个月的销售状况,增长年份列和月份列:
df['year'] = df["Order_Date"].dt.year df['month'] = df['Order_Date'].values.astype('datetime64[M]')
2.3 缺失值处理
查看缺失值状况:
df.isnull().sum(axis=0) ---------------------------- Row_ID 0 Order_ID 0 Order_Date 0 Ship_Date 0 Ship_Mode 0 Customer_ID 0 Customer_Name 0 Segment 0 City 0 State 0 Country 0 Postal_Code 41296 Market 0 Region 0 Product_ID 0 Category 0 Sub_Category 0 Product_Name 0 Sales 0 Quantity 0 Discount 0 Profit 0 Shipping_Cost 0 Order_Priority 0 year 0 month 0 dtype: int64
发现有一列缺失值比较多,此列表示邮编信息,对咱们的分析没有太多做用,可直接删除:
df.drop(["Postal_Code"],axis=1, inplace=True)
2.4 异常值处理
简单查看一下是否有异常值:
df.describe()
没发现明显的异常值,不须要进行处理。
2.5 重复值处理
看一下是否有重复值:
df.duplicated().sum() --------------------- 0
也没有重复值,不须要进行处理。
首先构造总体销售状况的数据集:
# 总体销售状况子数据集,包含下单日期、销售额、销量、利润、年份、月份信息 sales_data = df[['Order_Date','Sales','Quantity','Profit','year','month']] sales_data.sample(5) ------------------------------ Order_Date Sales Quantity Profit year month 45436 2014-11-27 38.040 2 12.1728 2014 2014-11-01 12625 2013-11-11 20.368 1 7.3834 2013 2013-11-01 24800 2011-11-15 40.320 7 14.0000 2011 2011-11-01 35508 2014-01-22 27.936 4 9.4284 2014 2014-01-01 39183 2013-06-24 179.880 6 61.0800 2013 2013-06-01
按照年份、月份对销售子数据集进行分组求和:
sales_year = sales_data.groupby(['year','month']).sum() sales_year
对以上数据进行拆分,每一年为一个表:
# slice(None), 是Python中的切片操做,这里用来选择所有数据 year_2011 = sales_year.loc[(2011,slice(None)),:].reset_index() year_2012 = sales_year.loc[(2012,slice(None)),:].reset_index() year_2013 = sales_year.loc[(2013,slice(None)),:].reset_index() year_2014 = sales_year.loc[(2014,slice(None)),:].reset_index() year_2014 # 看一下2014年的数据
1.1 销售额分析
构建销售表:
sales=pd.concat([year_2011['Sales'],year_2012['Sales'], year_2013['Sales'],year_2014['Sales']],axis=1) # 对行名和列名进行重命名 sales.columns=['Sales-2011','Sales-2012','Sales-2013','Sales-2014'] sales.index=['Jau','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] # 颜色越深,销售额越高 sales.style.background_gradient()
从上图能够看出,基本上每年都是下半年销售额比上半年要高,并且随着年份的增大,销售额也有明显的增长,说明销售业绩增加较快,发展仍是比较好的。
肉眼可见的是每年的销售额都比前一年要好,来实际计算一下具体的增加率和每一年的销售总额:
# 计算年度销售额并图表展现 sales_sum=sales.sum() sales_sum.plot(kind='bar',alpha=0.5) plt.grid() # 计算每一年增加率 rise_12=sales_sum[1]/sales_sum[0]-1 rise_13=sales_sum[2]/sales_sum[1]-1 rise_14=sales_sum[3]/sales_sum[2]-1 rise_rate=[0,rise_12,rise_13,rise_14] # 显示增加率 sales_sum=pd.DataFrame({'sales_sum':sales_sum}) sales_sum['rise_rate']=rise_rate sales_sum ------------------------------------------ sales_sum rise_rate Sales-2011 2.259451e+06 0.000000 Sales-2012 2.677439e+06 0.184995 Sales-2013 3.405746e+06 0.272017 Sales-2014 4.299866e+06 0.262533
从上面能够看出,后两年的销售额增加率达到26%,2014年销售额将近是2011的两倍,发展势头良好,经营在逐步稳定。结合年度销售额及增加率,再结合公司总体战略规划,能够预测或制定下一年度总销售额业绩指标。
了解了超市总体销售额后,再对每一年每个月的销售额进行分析,了解不一样月份的销售状况,找出是否有淡旺季之分,找出重点销售月份,以便制定经营策略与业绩月度及季度指标拆分。
看一下销售额的面积堆叠图:
# 面积堆叠图 sales.plot.area(stacked=False)
从上图能够大体看出,该超市的销售季节性明显,整体上半年是淡季,下半年是旺季。上半年中6月份销售额比较高,下半年中7月份的销售额偏低。
对于旺季的月份,运营推广等策略要继续维持,还能够加大投入,提升总体销售额。
对于淡季的月份,能够结合产品特色进行新产品拓展,举办一些促销活动等吸引客户。
1.2 销量分析
构建销量表:
quantity = pd.concat([year_2011['Quantity'],year_2012['Quantity'], year_2013['Quantity'],year_2014['Quantity']],axis=1) # 对行名和列名进行重命名 quantity.columns=['Quantity-2011','Quantity-2012','Quantity-2013','Quantity-2014'] quantity.index=['Jau','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] # 颜色越深,销量越高 quantity.style.background_gradient()
看一下销量增加率和每一年的销量总和:
# 计算年度销量并图表展现 quantity_sum=quantity.sum() quantity_sum.plot(kind='bar',alpha=0.5) plt.grid() # 计算每一年增加率 rise_12=quantity_sum[1]/quantity_sum[0]-1 rise_13=quantity_sum[2]/quantity_sum[1]-1 rise_14=quantity_sum[3]/quantity_sum[2]-1 rise_rate=[0,rise_12,rise_13,rise_14] # 显示增加率 quantity_sum=pd.DataFrame({'quantity_sum':quantity_sum}) quantity_sum['rise_rate']=rise_rate quantity_sum ------------------------------ quantity_sum rise_rate Quantity-2011 31443 0.000000 Quantity-2012 38111 0.212066 Quantity-2013 48136 0.263047 Quantity-2014 60622 0.259390
从上面能够看出,2011-2014年销量变化趋势与销售额是同样的,下半年销量总体高于上半年,同时销量同比上一年均在提升。
1.3 利润分析
构建利润表:
profit=pd.concat([year_2011['Profit'],year_2012['Profit'], year_2013['Profit'],year_2014['Profit']],axis=1) profit.columns=['Profit-2011','Profit-2012','Profit-2013','Profit-2014'] profit.index=['Jau','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] profit.style.background_gradient()
计算每一年总利润和利润率:
# 计算年度总利润并图表展现 profit_sum=profit.sum() profit_sum.plot(kind='bar',alpha=0.5) plt.grid() profit_sum=pd.DataFrame({'profit_sum':profit_sum}) profit_sum["year"] = [2011, 2012, 2013, 2014] sales_sum=pd.DataFrame({'sales_sum':sales.sum()}) sales_sum["year"] = [2011, 2012, 2013, 2014] profit_sum = pd.merge(profit_sum, sales_sum) profit_sum["profit_rate"] = profit_sum["profit_sum"] / profit_sum["sales_sum"] profit_sum ----------------------------- profit_sum year sales_sum profit_rate 0 248940.81154 2011 2.259451e+06 0.110178 1 307415.27910 2012 2.677439e+06 0.114817 2 406935.23018 2013 3.405746e+06 0.119485 3 504165.97046 2014 4.299866e+06 0.117252
从上面的结果能够看出,每一年的利润和销售额同样,是在逐年增长的,说明企业经营仍是比较妥善的,可是利润率整体平稳,稳定在11%-12%之间,整体利润率也仍是不错的。
1.4 客单价分析
客单价是指商场(超市)每个顾客平均购买商品的金额,客单价也便是平均交易金额。从某种程度上反映了企业的消费群体的许多特色以及企业的销售类目的盈利状态是否健康。
总消费次数:同一天内,同一我的发生的全部消费算做一次消费。
客单价=总消费金额 / 总消费次数
# 2011-2014年客单价 for i in range(2011,2015): data=df[df['year']==i] price=data[['Order_Date','Customer_ID','Sales']] # 计算总消费次数 price_dr=price.drop_duplicates( subset=['Order_Date', 'Customer_ID']) # 总消费次数:有多少行 total_num=price_dr.shape[0] print('{}年总消费次数='.format(i),total_num) unit_price = price['Sales'].sum()/total_num print('{}年客单价='.format(i), unit_price,'\n') --------------------------------------------------- 2011年总消费次数= 4453 2011年客单价= 507.3997070604087 2012年总消费次数= 5392 2012年客单价= 496.55762136498515 2013年总消费次数= 6753 2013年客单价= 504.3308824788983 2014年总消费次数= 8696 2014年客单价= 494.4647965225392
从上面结果来看,每一年的消费次数呈不断上升趋势,可是客单价整体浮动范围不是很大 ,稳定在500左右。
1.5 市场布局分析
由于这是一家全球超市,在不一样地区都会有市场,因此看一下不一样地区之间的销售状况:
Market_Year_Sales = df.groupby(['Market', 'year']).agg({'Sales':'sum'}).reset_index().rename(columns={'Sales':'Sales_amounts'}) Market_Year_Sales.head() -------------------------------- Market year Sales_amounts 0 APAC 2011 6.392453e+05 1 APAC 2012 7.627193e+05 2 APAC 2013 9.745809e+05 3 APAC 2014 1.209199e+06 4 Africa 2011 1.271873e+05
用图表显示各个地区每一年的销售状况:
sns.barplot(x='Market', y='Sales_amounts', hue='year', data = Market_Year_Sales) plt.title('2011-2014 market sales')
再看一下四年来各个地区销售额占总销售额的百分比:
Market_Sales = df.groupby(['Market']).agg({'Sales':'sum'}) Market_Sales["percent"] = Market_Sales["Sales"] / df["Sales"].sum() Market_Sales.style.background_gradient()
从以上图表能够看出,每一个地区每一年销售额整体处于上升趋势,其中APAC(亚太地区)、EU(欧盟)、US(美国)、LATAM(拉丁美洲)的销售额超过了总销售额的85%,整体也与地区的经济发展相匹配。其中加拿大Canada的销售额微乎其微,能够结合公司总体战略布局进行取舍。
先看一下销量前10名的商品:
productId_count = df.groupby('Product_ID').count()['Customer_ID'].sort_values(ascending=False) print(productId_count.head(10)) -------------------------------------- Product_ID OFF-AR-10003651 35 OFF-AR-10003829 31 OFF-BI-10002799 30 OFF-BI-10003708 30 FUR-CH-10003354 28 OFF-BI-10002570 27 OFF-BI-10004140 25 OFF-BI-10004195 24 OFF-BI-10001808 24 OFF-BI-10004632 24 Name: Customer_ID, dtype: int64
销售额前10名的商品:
productId_amount = df.groupby('Product_ID').sum()['Sales'].sort_values(ascending=False) print(productId_amount.head(10)) ----------------------------------- Product_ID TEC-CO-10004722 61599.8240 TEC-PH-10004664 30041.5482 OFF-BI-10003527 27453.3840 TEC-MA-10002412 22638.4800 TEC-PH-10004823 22262.1000 FUR-CH-10002024 21870.5760 FUR-CH-10000027 21329.7300 OFF-AP-10004512 21147.0840 FUR-TA-10001889 20730.7557 OFF-BI-10001359 19823.4790 Name: Sales, dtype: float64
从上面能够看出,销量最高的大部分是办公用品,而销售额最高的大部分是电子产品、家具这些单价较高的商品。
利润前10的商品:
productId_Profit= df.groupby('Product_ID').sum()['Profit'].sort_values(ascending=False) print(productId_Profit.head(10)) ------------------------------------ Product_ID TEC-CO-10004722 25199.9280 OFF-AP-10004512 10345.5840 TEC-PH-10004823 8121.4800 OFF-BI-10003527 7753.0390 TEC-CO-10001449 6983.8836 FUR-CH-10002250 6123.2553 TEC-PH-10004664 5455.9482 OFF-AP-10002330 5452.4640 TEC-PH-10000303 5356.8060 FUR-CH-10002203 5003.1000 Name: Profit, dtype: float64
利润前10的商品有一半是电子产品,能够重点考虑提高这部分产品的销量,来增长总体的利润。
具体商品种类的销售状况:
# 根据商品种类和子种类,从新重合成一个新的种类 df['Category_Sub_Category'] = df[['Category','Sub_Category']].apply(lambda x:str(x[0])+'_'+str(x[1]),axis=1) # 按照新的种类进行分组,统计销售额和利润 df_Category_Sub_Category=df.groupby("Category_Sub_Category").agg({"Profit":"sum","Sales":"sum"}).reset_index() # 按照销售额倒序排序 df_Category_Sub_Category.sort_values(by=["Sales"],ascending=False, inplace=True) # 每一个种类商品的销售额累计占比 df_Category_Sub_Category['cum_percent'] = df_Category_Sub_Category['Sales'].cumsum()/df_Category_Sub_Category['Sales'].sum() df_Category_Sub_Category
从图表中能够很清晰的看到不一样种类商品的销售额贡献对比,有将近一半的商品的总销售占比达到84%,应该是自家优点主营产品,后续经营中应继续保持,能够结合总体战略发展适当加大投入,逐渐造成本身的品牌。
同时,也能够发现,末尾占比16%的产品中大部分是办公用品中的小物件。能够考虑与其余主营产品结合,连带销售来提高销量,或者考虑对这些商品进行优化。
可是值得关注的是,Tables(桌子)的利润是负,代表这个产品目前处于亏损状态,应该是促销让利太多。经过检查原数据,发现Tabels大部分都在打折,打折的销量高达76%。若是是在清库存,这个效果仍是不错的,但若是不是,说明这个产品在市场推广上遇到了瓶颈,或者是遇到强竞争对手,须要结合实际业务进行分析,适当改善经营策略。
3.1 不一样类型的客户占比
df["Segment"].value_counts().plot(kind='pie', autopct='%.2f%%', shadow=True, figsize=(14, 6))
从上图能够看出,这四年来,普通消费者的客户占比最多,达到51.7%。
再看一下每年不一样类型的客户数量状况:
Segment_Year = df.groupby(["Segment", 'year']).agg({'Customer_ID':'count'}).reset_index() sns.barplot(x='Segment', y='Customer_ID', hue='year', data = Segment_Year) plt.title('2011-2014 Segment Customer')
从上面能够看出,每类客户每一年均在保持增加趋势,客户结构仍是很是不错的。
看一下不一样类型的客户每一年贡献的销售额:
Segment_sales = df.groupby(["Segment", 'year']).agg({'Sales':'sum'}).reset_index() sns.barplot(x='Segment', y='Sales', hue='year', data = Segment_sales) plt.title('2011-2014 Segment Sales')
各个类型的客户每一年贡献的销售额都在稳步提高,普通消费者贡献的销售额最多,这和客户占比也有必定关系。
3.2 客户下单行为分析
首先截取Customer_ID, Order_Date, Quantity, Sales, month为新的子集,并对Order_Date进行排序,方便后续分析 :
grouped_Customer = df[['Customer_ID','Order_Date', 'Quantity', 'Sales', 'month']].sort_values(['Order_Date']).groupby('Customer_ID') grouped_Customer.head()
看一下用户的第一次购买日期分布:
grouped_Customer.min().Order_Date.value_counts().plot()
再来看一下用户的最后一次购买日期分布:
grouped_Customer.max().Order_Date.value_counts().plot()
从上面能够看出, 在13年初之后新用户增加的趋势缓慢,商家能够经过广告等推广策略吸取更多的新用户;而经过观察最近一次购买日期,能够发现用户基本没有流失,也验证了每一年销售额的增加趋势。
整体来讲新客户数量是在逐年递减的,说明该企业老客户的维系不错,但新客获取率较低。若是可以在新客户获取上可以突破,会给企业带来很大的增加空间。
再来看看只购买过一次的客户数量 :
# 统计每一个客户第一次和最后一次购买记录 Customer_life = grouped_Customer.Order_Date.agg(['min','max']) # 查看只有一次购买记录的顾客数量,第一次和最后一次是同一条记录,则说明购买只有一次 (Customer_life['min'] == Customer_life['max']).value_counts() ----------------------------------------------------- False 1580 True 10 dtype: int64
从结果来看,只购买一次的用户只有10个,大部分用户都会购买屡次,说明回头率很高,也验证了上面关于该企业老客户的维系不错的结论。
3.3 RFM模型分析
RFM的含义:
R(Recency):客户最近一次交易时间的间隔。R值越大,表示客户交易发生的日期越久,反之则表示客户交易发生的日期越近。
F(Frequency):客户在最近一段时间内交易的次数。F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃。
M(Monetary):客户在最近一段时间内交易的金额。M值越大,表示客户价值越高,反之则表示客户价值越低。
RFM分析就是根据客户活跃程度和交易金额的贡献,进行客户价值细分的一种方法。
首先构建RFM表:
rfm = df.pivot_table(index='Customer_ID', values = ["Quantity","Sales","Order_Date"], aggfunc={"Quantity":"sum","Sales":"sum","Order_Date":"max"}) # 全部用户最大的交易日期为标准,求每笔交易的时间间隔即为R rfm['R'] = (rfm.Order_Date.max() - rfm.Order_Date)/np.timedelta64(1,'D') # 每一个客户的总销量即为F,总销售额即为M rfm.rename(columns={'Quantity':'F','Sales':'M'},inplace = True) rfm.head()
接着对客户价值进行标注,将客户分为8个等级(2 x 2 x 2):
# 基于平均值作比较,超过均值为1,不然为0 rfm[['R','F','M']].apply(lambda x:x-x.mean()) def rfm_func(x): level =x.apply(lambda x:'1'if x>0 else '0') level =level.R +level.F +level.M d = { "111":"重要价值客户", "011":"重要保持客户", "101":"重要挽留客户", "001":"重要发展客户", "110":"通常价值客户", "010":"通常保持客户", "100":"通常挽留客户", "000":"通常发展客户" } result = d[level] return result rfm['label']= rfm[['R','F','M']].apply(lambda x:x-x.mean()).apply(rfm_func,axis =1) rfm.head()
对重要价值客户和非重要价值客户进行可视化展现:
rfm.loc[rfm.label=='重要价值客户','color']='g' rfm.loc[~(rfm.label=='重要价值客户'),'color']='r' rfm.plot.scatter('F','R',c= rfm.color)
经过RFM识别不一样的客户群体,可以衡量客户价值和客户利润创收能力,能够指定个性化的沟通和营销服务,为更多的营销决策提供有力支持,为企业创造更大的利益。
3.4 新用户、活跃用户、不活跃用户和回归用户分析
设置Customer_ID为索引,month为列名,统计每月的购买次数:
pivoted_counts = df.pivot_table(index= 'Customer_ID', columns= 'month', values= 'Order_Date', aggfunc= 'count').fillna(0) # 大于一次的所有设为1 df_purchase = pivoted_counts.applymap(lambda x:1 if x>0 else 0) df_purchase.head() python数据分析实战之超市零售分析 定义状态函数并进行状态标记: def active_status(data): status = [] for i in range(48): if data[i] == 0: if len(status)>0: if status[i-1] == "unreg": # 未注册客户 status.append("unreg") else: # 不活跃用户 status.append("unactive") else: status.append("unreg") # 若本月消费了 else: if len(status) == 0: # 新用户 status.append("new") else: if status[i-1] == "unactive": # 回归用户 status.append("return") elif status[i-1] == "unreg": status.append("new") else: status.append("active") return pd.Series(status) purchase_stats = df_purchase.apply(active_status,axis =1) purchase_stats.head()
用NaN替代 “unreg”,并统计每个月各状态客户数量:
purchase_stats_ct = purchase_stats.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x)) # 用0填充NaN purchase_stats_ct.fillna(0).T.plot.area()
从以上结果能够发现活跃客户、新客户和回归客户,每一年呈必定的规律起伏,这可能和年长年末大促有关,须要更多数据进行佐证;同时能够发现新客数量每一年均在减小,说明该商家新客获取率较低,若是能在新客户获取上取得突破,会给商家带来很大的增加空间。
3.5 复购率和回购率分析
复购率计算指标:用户在该月购买过一次以上算复购。
purchase_r = pivoted_counts.applymap(lambda x :1 if x>1 else np.NaN if x==0 else 0) (purchase_r.sum()/purchase_r.count()).plot(figsize=(10,4))
回购率计算指标:在该月购买过,且在下月也购买时计入回购。
def purchase_back(data): status=[] for i in range(47): if data[i] ==1: if data[i+1] == 1: status.append(1) if data[i+1] == 0: status.append(0) else: status.append(np.NaN) status.append(np.NaN) return status purchase_b = df_purchase.apply(purchase_back,axis =1,result_type='expand') (purchase_b.sum()/purchase_b.count()).plot(figsize=(10,4))
从上能够发现复购率基本大于0.525,且呈整体上升趋势,说明客户忠诚度高,回购率在年中年底呈峰形态,可能与商家折扣活动或节日有关。
本文分别经过“场、货、人”三个不一样的角度去分析一家全球超市的销售、商品、用户状况,并根据分析结果给出一些有利于拓展用户、提高销量的办法。
固然,这份数据集包含信息不少,还能够进行其它一些方面的分析,来给出更好的建议。
文源网络,仅供学习之用,若有侵权请联系删除。在学习Python的道路上确定会碰见困难,别慌,我这里有一套学习资料,包含40+本电子书,800+个教学视频,涉及Python基础、爬虫、框架、数据分析、机器学习等,不怕你学不会!
https://shimo.im/docs/JWCghr8... 《Python学习资料》关注公众号【Python圈子】,优质文章每日送达。