嗨喽! 大家好,我是“流水不争先,争得滔滔不绝”的翀,18双非本科生一枚,正在努力!欢迎大家来交流学习,一起学习数据分析,希望我们一起好好学习,天天向上,目前是小社畜一枚~~
项目名称 新零售无人智能售货机1.数据探索1.1数据读取1.2 设备编号1.3 订单编号1.4 支付状态1.5 收款方2. 数据预处理2.1 提取城市信息和商品更新2.2 提取商品名称及数量3. 数据分析3.1 分析商品销售排行榜3.2 分析某一台设备不同时间的销售情况3.3 分析某一台设备不同星期的销售情况3.4 某一台设备不同时间的销售情况4. 不同时间的销售情况5. 分析城市销售情况5.1 绘制地理图表展示城市之间的空间关系6. 销售额环比6.1 周环比6.2 月环比6.3 广州地区的周环比7 不同商品单价的销售情况总结
项目类型 数据分析类
自动售货机以线上经营的理念,提供线下的便利服务,以小巧、自助的经
营模式节省人工成本,让实惠、高品质的商品触手可及,成为当下零售经
营的又一主流模式。自动售货机内商品的供给频率、种类选择、供给量、
项目背景 站点选择等是自动售货机运营者需要重点关注的问题。因此,科学的商业 数据分析能够帮助经营者了解用户需求,掌握商品需求量,为用户提供精 准贴心的服务,是掌握经营方向的重要手段,对自动售货机这一营销模式 的发展有着非常重要的意义。
项目目标 本项目对售货机销售数据进行商务数据分析,帮助经营者了解用户需求, 掌握商品需求量,给出合理的营销方案。
项目数据 5 台不同地点的自动售货机一年的销售数据。
项目难度
TASK1:数据预处理与分析
TASK1.1 根据实际项目需求对数据进行预处理
TASK1.2 计算每台售货机每个月平均交易额和日均订单量
TASK2 :数据可视化
TASK2.1 掌握 python 可视化基础,了解可视化含义
任务清单 TASK2.2 对 TASK1 处理后的数据进行可视化分析,并给出分析结论 TASK3 :售货机画像的探索 TASK3.1 根据热销商品绘制分别绘制 5 台售货机画像 TASK3.2 根据画像及分析制定合适的营销策略 TASK4 :预测 TASK4.1 预测售货机近三个月内热销前 10 的商品未来一个月的销量 TASK4.2 根据预测值,给出 5 台售货机未来一个月货品补充计划
1.数据探索1.1数据读取import warnings
warnings.filterwarnings('ignore')
import datetime
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import re
import os
#数据探索
#1 获取所有文件的名称和路径
data_path = './data/' #数据存储路径
data_names = os.listdir(data_path) #列举出data_path里面所有的文件名称
data = pd.DataFrame([])
for data_name in data_names:
# 删除不是的文件
if data_name.endswith('.csv'):
print((data_name))
#3 循环读取文件
tmp =pd.read_csv(os.path.join(data_path,data_name),encoding='gbk')
#4 文件存储
data = pd.concat([data,tmp])
#data = pd.read_csv('./data/订单表2018-5.csv',encoding='gbk') #读取
data.head()
data.info() #数据总览
data.columns

#查看缺失情况
data.isnull().sum()
ind = data['收款方'].isnull()
data.loc[ind,:]
ind = data['出货状态'].isnull()
data.loc[ind,:]

1.2 设备编号ind = data['商品详情'].apply(lambda x:'嗨购中奖' in x)
data.loc[ind,:]
# 1.3 设备编号
data ['设备编号'].value_counts() #值统计
ind = data['设备编号'] == 112866
data.loc[ind,'省市区'].value_counts()

1.3 订单编号# 1.4 订单编号
data['订单编号'].value_counts() # 正确 发现全部是唯一的

`
1.4 支付状态# 1.5 支付状态
num = data['支付状态'].value_counts()
plt.rcParams['font.sans-serif'] = 'SimHei' #字体设置,不然显示不了中文图片中
plt.pie(num, autopct='%.2f%%', labels=num.index)
plt.title('支付方式占比情况')
plt.show()

1.5 收款方# 1.7 收款方
data['收款方'].value_counts()
ind = data['收款方'] =='售货机自收'
data.loc[ind, :]
# 1.8省市区
data['省市区'].value_counts()
# 2 数据预处理
# 2.1 下单时间修改为时间格式的数据
data['下单时间'] =pd.to_datetime(data['下单时间'],errors='coerce')
#data['下单时间'].dt.weekday_name
# 2.2 出货状态只保留"出货正常"的数据
ind = data['出货状态'] =='出货成功'
data2 =data.loc[ind,:]
# 2.3 提取城市信息
data2['city'] = data2['省市区'].apply((lambda x: re.findall('.{2}市',x)[0]))
data2['city'].value_counts()2. 数据预处理

2.1 提取城市信息和商品更新# 2.3 提取城市信息
data2['city'] = data2['省市区'].apply((lambda x: re.findall('.{2}市',x)[0]))
data2['city'].value_counts()
# 2.4商品名称更新
data2['商品详情'] = data2['商品详情'].str.replace('百事可以', '百事可乐')
data2['商品详情'] = data2['商品详情'].str.replace('苿莉花茶', '茉莉花茶')
data2['商品详情'] = data2['商品详情'].str.replace('茶TT', '茶π')
data2['商品详情'] = data2['商品详情'].str.replace('nl', '')
data2['商品详情'] = data2['商品详情'].str.replace('毫升', '')
data2['商品详情'] = data2['商品详情'].str.replace('乐事薯片', '乐事')
data2['商品详情'] = data2['商品详情'].apply(lambda x: re.sub('([^;,xX]+)?|[罐瓶盒]装?|', '', x))
data2['商品详情'] = data2['商品详情'].str.replace('马蒂爽', '马蹄爽')
data2['商品详情'] = data2['商品详情'].str.replace('鲜蘑豆奶', '鲜磨豆奶')
data2['商品详情'] = data2['商品详情'].apply(lambda x: re.sub('广氏菠萝啤|廣式菠萝啤|菠萝啤酒', '菠萝啤', x))
data2['商品详情'] = data2['商品详情'].str.replace('威化瓶干', '威化饼干')
data2['商品详情'] = data2['商品详情'].str.replace('康师父', '康师傅')
data2['商品详情'] = data2['商品详情'].str.replace('张三疯', '张三丰')
data2['商品详情'] = data2['商品详情'].str.replace('蓝莓味', '蓝莓')
data2['商品详情'] = data2['商品详情'].str.replace('西柚味', '西柚')
data2['商品详情'] = data2['商品详情'].str.replace('柠檬味', '柠檬')
data2['商品详情'] = data2['商品详情'].apply(lambda x: re.sub('水蜜桃[^;,xX]+', '蜜桃', x))
data2['商品详情'] = data2['商品详情'].apply(lambda x: re.sub('青柠[^;,xX]+', '青柠', x))
data2['商品详情'] = data2['商品详情'].str.upper()
data2['商品详情'] = data2['商品详情'].str.replace('ML', '')
# 2.5 提取商品名称及数量
t = data2['商品详情'].apply(lambda x: re.findall('([^,;xX]+) ?[Xx]([0-9]{1,2})', x))
from tkinter import _flatten
goods = t.apply(lambda x: list(_flatten(x))[::2])
numbers = t.apply(lambda x: list(_flatten(x))[1::2])
goods_data = pd.DataFrame({'goods': goods, 'numbers': numbers})
goods_data.head()2.2 提取商品名称及数量

flatten()函数用法
flatten是numpy.ndarray.flatten的一个函数,即返回一个一维数组。
flatten只能适用于numpy对象,即array或者mat,普通的list列表不适用!。
a.flatten():a是个数组,a.flatten()就是把a降到一维,默认是按行的方向降 。 a.flatten().A:a是个矩阵,降维后还是个矩阵,矩阵.A(等效于矩阵.getA())变成了数组。
names = _flatten(list(goods_data['goods']))
num = _flatten(list(goods_data['numbers']))
new_goods_data = pd.DataFrame({'产品名称':names,'购买数量':num})
new_goods_data.head()

3. 数据分析3.1 分析商品销售排行榜
分析商品销售排行榜:用户喜欢的商品有哪些?
畅销品 •目的:为运营服务(方便推荐(二八法则);商场摆设、采购、培训使得销售利润最大化) •确认畅销品的方法:销售量排名、二八法则、ABC法则
什么样的商品是畅销品? 1.只看销售量、销售额(销售量、销售额等) 2.销售不错且能持续提供库存支持的商品(销售量、销售额、库存量、库存天数、库存周数等) 3.只有能够持续给公司创造销售和利润,且占用最优资金量的商品(销售量、销售额、库存量、库存天数、库存周数、毛利率等特征)
new_goods_data.dtypes

new_goods_data.dtypes
new_goods_data['购买数量'] = new_goods_data['购买数量'].astype(int)
num = new_goods_data.groupby('产品名称').agg(sum).sort_values('购买数量', ascending=False)


plt.style.use('ggplot')
plt.barh(range(20), num['购买数量'][:20])
plt.yticks(range(20), num.index[:20])
plt.ylabel('产品名称')
plt.xlabel('销售量')
plt.title('销售量排行榜(前二十)')
plt.show()

可以看出这几个月销售量排行前20的商品
3.2 分析某一台设备不同时间的销售情况# 3.1分析某一台设备不同时间的销售情况
ind = data2['设备编号'] ==112866
data_112 = data2.loc[ind, :]
data_112.shape
data_112.columns

# 某一台设备不同日期的销售情况
data_112['date'] = data_112['下单时间'].dt.date
data_112['income'] = data_112['总金额(元)'] - data_112['退款金额(元)']
num = data_112[['date', 'income']].groupby('date').sum().sort_index()
plt.plot(num.index, num)
plt.xticks(num.index[::8], num.index[::8], rotation=90)
plt.show()

# 某一台设备不同日期的销售情况
data_112['date'] = data_112['下单时间'].dt.date
data_112['income'] = data_112['总金额(元)'] - data_112['退款金额(元)']
num = data_112[['date', 'income']].groupby('date').sum().sort_index()
plt.plot(num.index, num)
plt.xticks(num.index[::8], num.index[::8], rotation=90)
plt.show()

3.3 分析某一台设备不同星期的销售情况data_112['weekday'] = data_112['下单时间'].dt.weekday
num = data_112[['weekday', 'income']].groupby('weekday').sum().sort_index()
plt.plot(num.index, num)
plt.xticks(num.index, num.index, rotation=90)
plt.show()

data_112['month'] = data_112['下单时间'].dt.month
num = data_112[['weekday', 'income', 'month']].groupby(['month', 'weekday']).sum()
num = num.unstack() #最内层的行索引还原成了列索引
week = [0, 1, 2, 3, 4, 5, 6]
num2 = num.loc[:, [('income', i) for i in week]]
for i in range(5, 10):
plt.plot(week, num2.loc[i, :])
plt.legend([f'{i}月' for i in range(5, 10)])
plt.show()

3.4 某一台设备不同时间的销售情况# 3.3某一台设备不同时间的销售情况
data_112['hour'] = data_112['下单时间'].dt.hour
num = data_112[['hour','income']].groupby('hour').sum().sort_index()
plt.plot(num.index,num)
plt.xticks(num.index,num.index,rotation=90) #rotation旋转角度下标
plt.show()

data_112['hour'] = data_112['下单时间'].dt.hour
num = data_112[['hour','income','month']].groupby(['month','hour']).sum()
num = num.unstack().fillna(0) #fillna 缺失值填为0
for i in range(5, 10):
plt.plot(range(24), num.loc[i, :])
plt.legend([f'{i}月' for i in range(5, 10)])
plt.show()

#星期
data_112['hour'] = data_112['下单时间'].dt.hour
num = data_112[['hour', 'income', 'weekday']].groupby(['weekday', 'hour', ]).sum()
num = num.unstack().fillna(0)
for i in num.index:
plt.plot(range(24), num.loc[i, :])
plt.legend(num.index)
plt.show()

4. 不同时间的销售情况# 不同日期的销售情况
data2['date'] = data2['下单时间'].dt.date
data2['income'] = data2['总金额(元)'] - data2['退款金额(元)']
num = data2[['date', 'income']].groupby('date').sum().sort_index()
plt.plot(num.index, num)
plt.xticks(num.index[::8], num.index[::8], rotation=90)
plt.show()

不同星期的销售情况
data2['weekday'] = data2['下单时间'].dt.weekday
num = data2[['weekday', 'income']].groupby('weekday').sum().sort_index()
num = num.loc[[0,1,2,3,4,5,6],:]
plt.plot(num.index, num)
plt.xticks(num.index, num.index, rotation=90)
plt.show()

5. 分析城市销售情况# 3.4 分析城市销售情况
num = data2[['city', 'income']].groupby('city').sum().sort_values('income')
plt.barh(num.index,num['income'])
plt.show()

5.1 绘制地理图表展示城市之间的空间关系# 绘制地理图表展示城市之间的空间关系
from pyecharts.charts import Geo, Map
import pyecharts.options as opts
from pyecharts.globals import ChartType
(
Geo()
.add_schema(maptype='广东')
.add('', [(i, int(j)) for i,j in zip(num.index, num['income'])],
type_=ChartType.EFFECT_SCATTER)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title='各个城市销售量情况', subtitle='2018/4-2018/9'),
visualmap_opts=opts.VisualMapOpts(max_=max(num.max()), is_piecewise=True)
)
).render('./各个城市销售量情况.html')

# 绘制地理图表展示不同月份不同城市之间的空间关系
from pyecharts.charts import Geo, Timeline
import pyecharts.options as opts
from pyecharts.globals import ChartType
data2['month'] = data2['下单时间'].dt.month
num = data2[['month', 'income', 'city']].groupby(['month', 'city']).sum()
num2 = num.unstack()
num2 = num2.fillna(0)
tmp = {}
for i in range(4, 10):
num = num2.loc[i, :]
tmp[i] = (
Geo()
.add_schema(maptype='广东')
.add('', [(i[1], int(j)) for i, j in zip(num.index, list(num.values))],
type_=ChartType.EFFECT_SCATTER)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title='各个城市销售量情况', subtitle='2018/4-2018/9'),
visualmap_opts=opts.VisualMapOpts(max_=max(num2.max()), is_piecewise=True)
)
)
tl = Timeline()
for i in range(4, 10):
tl.add(tmp[i], str(i)+'月')
tl.render('./各个城市销售量情况(含时间轴).html')

6. 销售额环比6.1 周环比# 3.5销售额环比
# 计算周的销售额环比
data2['week'] = data2['下单时间'].dt.week
# 1 计算每一周的销售额
tmp = data2[['week','income']].groupby('week').sum()
# 2 计算销售额环比: (本期销售额-上期销售额)/上期销售额
t2 = tmp.diff().iloc[1:, :] #第一个数据是空,因为没得比
t2.index = tmp.index[:-1 ]
num = t2/tmp #销售额的周环比
diff()方法是数组a[n]-a[n-1]的作用,对应(本期销售额-上期销售额)
# 可视化:双Y轴图像
fig = plt.figure(figsize=(6, 4))
ax1 = fig.add_subplot(111) # 添加子图
ax1.bar(tmp.index, tmp['income'])
ax1.set_ylabel('收入')
ax1.set_xlabel('周数')
ax1.set_title('自动售货机收入趋势图')
ax2 = ax1.twinx()
ax2.plot(tmp.index[1:], num.iloc[:-1, 0], 'b')
ax2.set_ylabel('环比增长率')
plt.show()

6.2 月环比# 计算月的销售额环比
# 1、计算每月的销售额
tmp = data2[['month', 'income']].groupby('month').sum()
# 2、计算销售额环比:(本期销售额-上期销售额)/上期销售额
t2 = tmp.diff().iloc[1:, :]
t2.index = tmp.index[:-1]
num = t2/tmp # 销售额的月环比# 可视化:双Y轴图像
fig = plt.figure(figsize=(6, 4))
ax1 = fig.add_subplot(111) # 添加子图
ax1.bar(tmp.index, tmp['income'])
ax1.set_ylabel('收入')
ax1.set_xlabel('月份')
ax1.set_title('自动售货机收入趋势图')
ax2 = ax1.twinx()
ax2.plot(tmp.index[1:], num.iloc[:-1, 0], 'b')
ax2.set_ylabel('环比增长率')
plt.show()

6.3 广州地区的周环比# 计算周的销售额环比
data_gz = data2.loc[data2['city'] == '广州市', :]
data_gz['week'] = data_gz['下单时间'].dt.week
# 1、计算每一周的销售额
tmp = data_gz[['week', 'income']].groupby('week').sum()
# 2、计算销售额环比:(本期销售额-上期销售额)/上期销售额
t2 = tmp.diff().iloc[1:, :]
t2.index = tmp.index[:-1]
num = t2/tmp # 销售额的周环比
num

# 可视化:双Y轴图像
fig = plt.figure(figsize=(6, 4))
ax1 = fig.add_subplot(111) # 添加子图
ax1.bar(tmp.index, tmp['income'])
ax1.set_ylabel('收入')
ax1.set_xlabel('周数')
ax1.set_title('自动售货机收入趋势图--广州地区')
ax2 = ax1.twinx()
ax2.plot(tmp.index[1:], num.iloc[:-1, 0], 'b')
ax2.set_ylabel('环比增长率')
plt.show()

7 不同商品单价的销售情况
1、获取商品单价 2、获取商品购买数量 3、划分单价区间 4、不同单价区间的销售情况
ind = data2['购买数量(个)'] == 1
data2['goods'] = data2['商品详情'].apply(lambda x: re.sub('[Xx]1[;,]?', '', x))
price_data = data2.loc[ind, ['goods', '总金额(元)']].drop_duplicates('goods')new_data = pd.merge(new_goods_data, price_data, how='left', left_on='产品名称', right_on='goods')
ind = new_data['goods'].isnull()
tmp_sets = new_data.loc[ind, '产品名称'].unique()
ind = data2['商品详情'].apply(lambda x: sum([i in x for i in tmp_sets])!=0)
tmp = data2.loc[ind, :].apply(lambda x: ([i for i in tmp_sets if i in x['商品详情']], x['购买数量(个)'], x['总金额(元)']), axis=1)
tmp = pd.DataFrame({'name':[i[0][0] for i in tmp], 'num':[i[1] for i in tmp], 'total_price': [i[2] for i in tmp]})
tmp['price'] = tmp['total_price']/tmp['num']
tmp2 = tmp.drop_duplicates('name')[['name', 'price']]new_data = pd.merge(new_data, tmp2, how='left', left_on='产品名称', right_on='name')ind = new_data['总金额(元)'].isnull()
new_data['单价'] = 0
new_data.loc[ind, '单价'] = new_data.loc[ind, 'price'].copy()
new_data.loc[~ind, '单价'] = new_data.loc[~ind, '总金额(元)'].copy()ind = new_data['单价'].notnull()
new_data = new_data.loc[ind, ['产品名称', '购买数量', '单价']]plt.hist(np.repeat(new_data['单价'], new_data['购买数量']), bins=50)
plt.show()

# 指定单价区间
bins = pd.IntervalIndex.from_tuples([(0, 2), (2, 5), (5, 10), (10, 20), (20, 52)])
new_data['bins'] = pd.cut(new_data['单价'], bins)
num = new_data[['bins', '购买数量']].groupby('bins').sum()
plt.bar(range(5), num['购买数量'])
plt.title('不同价格区间的销售情况')
plt.xlabel('价格区间')
plt.ylabel('购买数量')
plt.xticks(range(5), num.index)
plt.show()

plt.pie(num['购买数量'], labels=num.index, autopct='%.2f %%')
plt.title('不同价格区间的销售数量占比情况')
plt.show()

倾向量多价少的交易
货道排放的商品应该以低价商品为主
货道摆放的位置:人流量大、停留时间长的位置
总结