Python超市电商数据分析(一)
数据源概况:
本案例将对某大型超市的零售数据进行数据分析,通过了
解运营状况,做出合理的决策。详细字段是:
Row ID:行编号;
Order ID:订单ID;
Order Date:订单日期;
Ship Date:发货日期;
Ship Mode:发货模式;
Customer ID:客户ID;
Customer Name:客户姓名;
Segment:客户类别;
City:客户所在城市;
State:客户城市所在州;
Country:客户所在国家;
Postal Code:邮编;
Market:商店所属区域;
Region:商店所属州;
Product ID:产品ID;
Category:产品类别;
Sub-Category:产品子类别;
Product Name:产品名称;
Sales:销售额;
Quantity:销售量;
Discount:折扣;
Profit:利润;
Shipping Cost:发货成本;
Order Priority:订单优先级;
读取文件
# 加载数据分析需要使用的库
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('E:/market.csv',encoding='ISO-8859-1')
df.head()
#数据大小
df.shape
#数据分布情况
df.describe()
market.csv部分数据如下:
读取、清洗数据:
- 使用pandas的read_csv读取数据后,查看各列数据的空值情况,发现Postal Code字段(邮编字段)有空值,而且这一列不重要,所以首先删除掉Postal Code列;
#重命名列名
df.rename(columns = lambda x: x.replace(' ', '_').replace('-', '_'), inplace=True)
#1.查看各列数据的空值情况,发现Postal Code字段(邮编字段)有空值,而且这一列不重要,所以首先删除掉Postal Code列;
#查看缺失值
df.isnull().sum(axis=0)
#删除邮编信息列
df.drop(["Postal_Code"],axis=1, inplace=True)
- 使用DataFrame对象的describe()方法,没有发现异常数
据,所以,不必处理;
df.describe()
- 将Order Date订单日期字段的数据修改为datetime类型;
df["Order_Date"] = pd.to_datetime(df["Order_Date"])
- 为了后续分析方便,从订单日期中分别提取年、月、季度数
据,并添加三个列用来存取年、月、季度信息,分别为:’Order-year’,’Order-month’,’quarter’。
df['Order_year'] = df['Order_Date'].dt.year
df['Order_month'] = df['Order_Date'].values.astype('datetime64[M]')
df['quarter'] = df['Order_Date'].dt.quarter
数据分析:
利润分析
先根据年和月进行分组,再分别提取各年份(2011-2014
年)的数据,分析各年份对应月的利润情况。
# 整体销售情况子数据集,包含下单日期、销售额、销量、利润、年份、月份信息
sales_data = df[['Order_Date','Sales','Quantity','Profit','Order_year','Order_month']]
#按照年份、月份对销售子数据集进行分组求和
sales_year = sales_data.groupby(['Order_year','Order_month']).sum()
sales_year
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()
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()
客单价分析
客单价指商场(超市)每一个顾客平均购买商品的金额,客单
价反映顾客的购买水平;客单价=销售额÷成交顾客数
#客单价分析
#客单价指商场(超市)每一个顾客平均购买商品的金额,客单价反映顾客的购买水平;
#客单价=销售额÷成交顾客数
# 2011-2014年客单价
unit_prices = [] # 这里应该填充你计算出的客单价数据
years = list(range(2011, 2015)) # 年份列表
for i in range(2011,2015):
data=df[df['Order_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')
unit_prices.append(unit_price)
# 绘制柱状图
plt.bar(years, unit_prices, label='客单价')
# 设置图表的标题和轴标签
plt.title('每年客单价分布')
plt.xlabel('年份')
plt.ylabel('客单价')
# 显示图例
plt.legend()
# 显示图表
plt.show()
每年销售额与销售额的增长率分析
通过年份分组,计算每年的销售额总和
销售额增长率 = (本年销售额-上年销售额) / 上年销售额 * 100%
= 本年销售额 / 上年销售额 - 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
import pandas as pd
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
# 绘制销售额的条形图
bar_width = 0.5 # 条形图的宽度
sales_sum['sales_sum'].plot(kind='bar', color='b', ax=ax1, width=bar_width, position=0.5)
# 设置条形图的y轴标签
ax1.set_ylabel('销售额/元', color='b')
ax1.tick_params('y', colors='b')
# 添加第二个坐标轴来绘制增长率折线图
ax2 = ax1.twinx()
# 绘制增长率的折线图
sales_sum['rise_rate'].plot(kind='line', color='r', ax=ax2, marker='*', ms=5)
# 设置增长率的y轴标签
ax2.set_ylabel('增长率', color='r')
ax2.tick_params('y', colors='r')
# 添加标题和网格
plt.title('销售额与增长率')
plt.grid(axis='y', alpha=0.75)
# 显示图形
plt.show()
可以看出:该超市在2011-2014年销售额在稳步上升,说明企
业市场占有能力在不断提 高; 2012-2014年的增长率在增长后
趋于平稳,说明企业经营在逐步稳定
分析各个地区分店的销售额
- 查看不同区域分店的总销售额占比
#分析各个地区分店的销售额
#查看不同区域分店的总销售额占比
Market_Sales = df.groupby(['Market']).agg({'Sales':'sum'})
Market_Sales["percent"] = Market_Sales["Sales"] / df["Sales"].sum()
Market_Sales.style.background_gradient()
# 绘制饼图
plt.figure(figsize=(10, 7))
plt.pie(Market_Sales["percent"], labels=Market_Sales.index, autopct='%1.1f%%', startangle=140)
plt.title("不同区域分店的总销售额占比")
plt.axis('equal')
plt.show()
从该饼图可以看出:APAC、BJ两个地区的销售额比例很高,
总计占51.6%,Canada的销售总额占比最小,只有0.5%,可以
增加对该地区的营销。
- 分别对各个区域每年销售额分析
#分别对各个区域每年销售额分析
Market_Year_Sales = df.groupby(['Market', 'Order_year']).agg({'Sales':'sum'}).reset_index().rename(columns={'Sales':'Sales_amounts'})
Market_Year_Sales.head()
sns.barplot(x='Market', y='Sales_amounts', hue='Order_year', data = Market_Year_Sales)
plt.title('2011-2014 market sales')
由上面的条形图可看出,各个地区2011-2014年的销售总
额均是增长趋势, 其中APAC地区和EU地区的增长速度较快,
市场前景较好,下一年可以适当 加大运营成本。
- 分别对各个区域的不同类型产品销售额分析
#分别对各个区域的不同类型产品销售额分析
category_sales_area = data.groupby(by=['Market','Category'])['Sales'].sum()
category_sales_area
# 将分组后的多层索引设置成列数据
category_sales_area = category_sales_area.reset_index(level=[0,1])
# 使用数据透视表重新整理数据
category_sales_area = pd.pivot_table(category_sales_area,
index='Market',
columns='Category',
values='Sales')
# 绘制图形
category_sales_area.plot(kind = 'bar',
title = '不同类型产品在不同地区销售额对比',
figsize= (10,8)
)
由上图可看出,除了Canada地区以外,各大地区销售额都比较
高的是电子产品,可 以适当加大对各地区(除Canada地区)
该种类的投入,以便扩大优势。