数据为随机生成,不具有参考性,仅仅用作学习
数据类型有以下这些,其中detil_id为详细id,类似于索引,emp_id在这里用不到,所以这两个信息在这次项目中用不到。所以我们可以提前将这两列删除,不删除也没问题。为了统一,这里的所有图形均以柱状图绘制,如果有特殊需求,可以更改plt函数中的kind参数
要求:
分析:最出名的菜品前十名,用户点的菜品种类多少,哪个菜品收益最高,哪个客人菜品点的最多,餐厅一天内的黄金时间段,餐厅一个月内的黄金时间日,餐厅一个星期内的黄金时段
取前十个数据,以图形的方式表达出来。最后可以自定义执行脚本,生成想要生成的图片
代码拆分:
(1)前提工作:
import pandas as pd
import sys
import matplotlib.pyplot as plt
# 设置支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体#首先将三张分散的表传入变量,指名相对应的数据表。各位练习的时候记得更改路径
data1=pd.read_excel('D:\桌面\python实践项目\Excel\餐厅数据可视化(练习).xlsx',sheet_name='Sheet1')
data2=pd.read_excel('D:\桌面\python实践项目\Excel\餐厅数据可视化(练习).xlsx',sheet_name='Sheet2')
data3=pd.read_excel('D:\桌面\python实践项目\Excel\餐厅数据可视化(练习).xlsx',sheet_name='Sheet3')
#将三张表按列拼接为一整张表,以便后续的完整分析(concat函数,按行【属性】进行连接)
data=pd.concat([data1,data2,data3],axis=0)
#继续进行数据的预处理,将data中的所有空值按列进行删除
data=data.dropna(axis=1)
导入了三个库,pandas数据分析库,plt绘图库,还有sys脚本执行库。
将excel中的三张表合并到一个变量中
按行删除了所有的空值。(由于这张表中空值相对较少,所以解决的方式简单粗暴,如果空值较多,建议用replace函数将空值替换为0)
其他数据列的格式正确,没有明显错误,数据清洗完成。如果后续再出现脏数据的情况可以折回到这一板块再编写代码
(2)菜品频数维度分析:
#维度一:针对频数进行数据的可视化,保存到def自定义函数中,以便后续的调用
# 重要信息提炼:通过分组聚合的方式进行频数的统计
dish_famous=data.groupby('dishes_name').agg({'counts': 'sum'}).sort_values('counts', ascending=False)[:10]
def dimension_counts(dish_famous):#先通过plot函数绘出bar柱状图,然后绘出折线图,最后适当调整。注意,这里需要指定x和y轴分别是哪两列,因为plot函数默认将索引列当作x轴dish_famous.plot(kind='bar',fontsize=8)plt.xticks(rotation=16, color='b')plt.show()
这里通过分组聚合的方式,分组菜品名字,聚合(点菜的)数量列,按照数量列进行排序,通过切片的方式取前十名。将绘图的部分保存到自定义函数dimension_counts中。这里我根据菜品名字的长度对X轴上的标签做了旋转处理
效果:
可见Chicken,Beef和Soup最受欢迎
(3)消费类型维度分析:
#维度二:订单消费类型的统计。同理,先进行频数统计,然后进行绘图分析
#取出对应的两列,删除重复值,就能得到每个用户的点菜种类数量了
dish_order=data[['order_id','dishes_id']]
dish_order=dish_order.drop_duplicates()
dish_order=dish_order.groupby('order_id').agg({'dishes_id':'count'}).sort_values('dishes_id', ascending=False)[:10]
def dimension_orders(dish_order):dish_order.plot(kind='barh', fontsize=13)plt.title('客户是否追求菜品的多元化', fontproperties='STsong', fontsize=20)plt.ylabel('订单类别数量', fontproperties='STsong', fontsize=16)plt.show()
先取出对应的两列,再删除重复值(因为有的用户可能多次点同一个菜品,要去重统计菜品类别)
进行分组聚合排序切片后即可将该模块的变量传递给自定义函数dimension_orders中了。在dimension_orders自定义绘图函数中,我们选用条形图表示,以便直观地看到趋势变化
效果:由此可见,大部分客户一共点过3个菜,这个餐厅应该加强新菜品的宣传了,或者将(2)维度中的前三个菜品作为招牌
(4)订单消费金额和点菜数量维度分析:
#维度三:订单消费金额以及点菜数量的维度分析
# 逻辑还是和之前一样,先取出源数据框的关键信息然后保存到新建变量中,然后将这些变量作为形式参数传入自定义函数中完成绘图
# 对订单消费金额的提取。由于存在可能有一共用户id一次性点多道菜,这里我们给data列添加一个金额综合列,由于这里不需要保持数据的一致性,直接对源数据data更改
data['消费综合'] = data['counts'] * data['amounts']
dish_money_count = data.groupby('dishes_id').agg({'消费综合':'sum'}).sort_values('消费综合', ascending=False)
def dimension_counts_money(dish_money_count):dish_money_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=16, color='b')plt.title('菜品收益前十名', fontproperties='STsong', fontsize=20)plt.xlabel('菜品ID', fontproperties='STsong', fontsize=16)plt.ylabel('消费总额', fontproperties='STsong', fontsize=16)plt.show()# 点菜数量的维度分析
dish_order_count = data.groupby('order_id').agg({'counts':'sum'}).sort_values('counts', ascending=False)[:10]
def dimension_dish_count(dish_order_count):dish_order_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=16, color='b')plt.title('点菜最多的客人前十名', fontproperties='STsong', fontsize=20)plt.xlabel('订单ID', fontproperties='STsong', fontsize=16)plt.ylabel('数量', fontproperties='STsong', fontsize=16)plt.show()
这里的菜品消费总额需要在源数据中新建一列,将数量列和价钱列相乘得到。这里直接更改源数据的行为不太提倡,可能造成源数据data的臃肿。如果不考虑内存的画建议多建立几个DataFrame对应相应的模块
效果:
由此可见哪道菜(图中以菜品id形式展示)的经济收益最大。那些用户点单量最多, 也可以简单分析出大部分用户的食量来推断这些客户聚餐的团体大小。
(5)一天内黄金时间段分析:
#维度四:时间维度分析
# 这里日期的形式为xxxx-x-x xx:xx 是时间戳,包含的要素较多,要先将该列的数据进行拆分# 进行数据清洗,有可能该时间数据是脏数据 保存到新建变量time列中
data['time'] = pd.to_datetime(data['order_time'])
# 用lambda自定义函数将小时提取出来保存到新建的hour列中
data['hour'] = data['time'].apply(lambda x:x.hour)
# 分析一天内什么时间段点菜数量最多
time_count = data.groupby('hour').agg({'counts':'sum'}).sort_values('counts', ascending=False)[:10]
def dimension_time_count(time_count):time_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=0, color='b')plt.title('点菜最多的时间段', fontproperties='STsong', fontsize=20)plt.xlabel('时间', fontproperties='STsong', fontsize=16)plt.ylabel('数量', fontproperties='STsong', fontsize=16)plt.show()
首先进行数据清洗,将清洗后的时间列保存到新建列time中,然后通过apply遍历函数搭配lambda自定义函数将time列中的hour数据提炼出来,保存到hour新建列中。然后继续分组聚合操作,传递给dimension_time_count自定义绘图函数中
效果:
可见一天内11点人最多,其他时间点稀少
(6)月黄金时间段分析:
# 分析哪一天的订点菜数量最多,利用strftime函数进行详细信息的提取
data['day'] = data['time'].apply(lambda x: x.strftime('%Y-%m-%d'))
day_count = data.groupby('day').agg({'counts':'sum'}).sort_values('counts', ascending=False)[:10]
def dimension_daycount(day_count):day_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=18, color='b')plt.title('点菜最多的天数', fontproperties='STsong', fontsize=20)plt.xlabel('时间', fontproperties='STsong', fontsize=16)plt.ylabel('数量', fontproperties='STsong', fontsize=16)plt.show()
想要提取特定的时间段,可以用strftime进行转换,该函数转换后的数据为一维(列)形式,可以直接遍历保存到新建列中。
效果:
7月的三天入选2016年最火爆的时间点,其他月份生意惨淡,均小于5人
(7)星期几最火爆:
# 分析周几人最多,映射到星期
data['week'] = data['time'].apply(lambda x:x.weekday())
week_count=data.groupby('week').agg({'order_id':'count'}).sort_values('order_id', ascending=False)[:10]
def dimension_weekcount(week_count):week_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=10, color='b')plt.title('人数最多的星期', fontproperties='STsong', fontsize=20)plt.xlabel('时间', fontproperties='STsong', fontsize=16)plt.ylabel('客人数量', fontproperties='STsong', fontsize=16)plt.show()
同上,先提炼出星期格式的数据列,然后用“星期列”进行分组聚合
效果:
可见周四周五周六效果更好,该餐厅适合周末做促销活动
(8)脚本运行入口设置:
#进行程序的交互设计if __name__ == '__main__':a=input("请输入你想绘制的图形:(最欢迎的菜品/菜品类别统计/菜品收益统计/客人的饭量统计/黄金时段统计/月最火爆的天数统计/最火爆的周天数")if a == '最欢迎的菜品':print(dimension_counts(dish_famous))print('绘制完成!程序结束')sys.exit()elif a == '菜品类别统计':print(dimension_orders(dish_order))print('绘制完成!程序结束')sys.exit()elif a == '菜品收益统计':print(dimension_counts_money(dish_money_count))print('绘制完成!程序结束')sys.exit()elif a == '客人的饭量统计':print(dimension_dish_count(dish_order_count))print('绘制完成!程序结束')sys.exit()elif a == '黄金时段统计':print(dimension_time_count(time_count))print('绘制完成!程序结束')sys.exit()elif a == '月最火爆的天数统计':print(dimension_daycount(day_count))print('绘制完成!程序结束')sys.exit()elif a == '最火爆的周天数':print(dimension_weekcount(week_count))print('绘制完成!')sys.exit()else:print('输入错误,请输入括号内提示的图形种类')print('执行完毕,无图可画')sys.exit()
在交互中,通过简单的if语句对所有出现过的情况进行分类,用户只需输入自己想要的分析图形即可生成对应的图形。
由此可见,这整个代码是最简单的面向过程编程。
可以通过正则表达式来简化用户输入的信息。
效果:
可见自动生成:
完整代码:
#数据要求:有多个客户id对不同的类别进行了交互,其中的不同列代表客户对类型的交互属性。例如:客户id/客户年龄/消费类别/消费个数/消费资金
#项目要求:实现菜品本身销量维度,关于食客消费的不同维度(点菜种类、点菜数量、订单的消费总额、订单的平均消费),消费时间的维度
#经典的面向过程编程import pandas as pd
import sys
import matplotlib.pyplot as plt
# 设置支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体#首先将三张分散的表传入变量,指名相对应的数据表
data1=pd.read_excel('D:\桌面\python实践项目\Excel\餐厅数据可视化(练习).xlsx',sheet_name='Sheet1')
data2=pd.read_excel('D:\桌面\python实践项目\Excel\餐厅数据可视化(练习).xlsx',sheet_name='Sheet2')
data3=pd.read_excel('D:\桌面\python实践项目\Excel\餐厅数据可视化(练习).xlsx',sheet_name='Sheet3')
#将三张表按列拼接为一整张表,以便后续的完整分析(concat函数,按行【属性】进行连接)
data=pd.concat([data1,data2,data3],axis=0)
#继续进行数据的预处理,将data中的所有空值按列进行删除
data=data.dropna(axis=1)#维度一:针对频数进行数据的可视化,保存到def自定义函数中,以便后续的调用
# 重要信息提炼:通过分组聚合的方式进行频数的统计
dish_famous=data.groupby('dishes_name').agg({'counts': 'sum'}).sort_values('counts', ascending=False)[:10]
def dimension_counts(dish_famous):#先通过plot函数绘出bar柱状图,然后绘出折线图,最后适当调整。注意,这里需要指定x和y轴分别是哪两列,因为plot函数默认将索引列当作x轴dish_famous.plot(kind='bar',fontsize=8)plt.xticks(rotation=16, color='b')plt.show()#维度二:订单消费类型的统计。同理,先进行频数统计,然后进行绘图分析
#取出对应的两列,删除重复值,就能得到每个用户的点菜种类数量了
dish_order=data[['order_id','dishes_id']]
dish_order=dish_order.drop_duplicates()
dish_order=dish_order.groupby('order_id').agg({'dishes_id':'count'}).sort_values('dishes_id', ascending=False)[:10]
def dimension_orders(dish_order):dish_order.plot(kind='barh', fontsize=13)plt.title('客户是否追求菜品的多元化', fontproperties='STsong', fontsize=20)plt.ylabel('订单类别数量', fontproperties='STsong', fontsize=16)plt.show()#维度三:订单消费金额以及点菜数量的维度分析
# 逻辑还是和之前一样,先取出源数据框的关键信息然后保存到新建变量中,然后将这些变量作为形式参数传入自定义函数中完成绘图
# 对订单消费金额的提取。由于存在可能有一共用户id一次性点多道菜,这里我们给data列添加一个金额综合列,由于这里不需要保持数据的一致性,直接对源数据data更改
data['消费综合'] = data['counts'] * data['amounts']
dish_money_count = data.groupby('dishes_id').agg({'消费综合':'sum'}).sort_values('消费综合', ascending=False)
def dimension_counts_money(dish_money_count):dish_money_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=33, color='b')plt.title('菜品收益前十名', fontproperties='STsong', fontsize=20)plt.xlabel('菜品ID', fontproperties='STsong', fontsize=16)plt.ylabel('消费总额', fontproperties='STsong', fontsize=16)plt.show()# 点菜数量的维度分析
dish_order_count = data.groupby('order_id').agg({'counts':'sum'}).sort_values('counts', ascending=False)[:10]
def dimension_dish_count(dish_order_count):dish_order_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=16, color='b')plt.title('点菜最多的客人前十名', fontproperties='STsong', fontsize=20)plt.xlabel('订单ID', fontproperties='STsong', fontsize=16)plt.ylabel('数量', fontproperties='STsong', fontsize=16)plt.show()#维度四:时间维度分析
# 这里日期的形式为xxxx-x-x xx:xx 是时间戳,包含的要素较多,要先将该列的数据进行拆分# 进行数据清洗,有可能该时间数据是脏数据 保存到新建变量time列中
data['time'] = pd.to_datetime(data['order_time'])
# 用lambda自定义函数将小时提取出来保存到新建的hour列中
data['hour'] = data['time'].apply(lambda x:x.hour)
# 分析一天内什么时间段点菜数量最多
time_count = data.groupby('hour').agg({'counts':'sum'}).sort_values('counts', ascending=False)[:10]
def dimension_time_count(time_count):time_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=0, color='b')plt.title('点菜最多的时间段', fontproperties='STsong', fontsize=20)plt.xlabel('时间', fontproperties='STsong', fontsize=16)plt.ylabel('数量', fontproperties='STsong', fontsize=16)plt.show()# 分析哪一天的订点菜数量最多,利用strftime函数进行详细信息的提取
data['day'] = data['time'].apply(lambda x: x.strftime('%Y-%m-%d'))
day_count = data.groupby('day').agg({'counts':'sum'}).sort_values('counts', ascending=False)[:10]
def dimension_daycount(day_count):day_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=18, color='b')plt.title('点菜最多的天数', fontproperties='STsong', fontsize=20)plt.xlabel('时间', fontproperties='STsong', fontsize=16)plt.ylabel('数量', fontproperties='STsong', fontsize=16)plt.show()# 分析周几人最多,映射到星期
data['week'] = data['time'].apply(lambda x:x.weekday())
week_count=data.groupby('week').agg({'order_id':'count'}).sort_values('order_id', ascending=False)[:10]
def dimension_weekcount(week_count):week_count.plot(kind='bar', fontsize=13)plt.xticks(rotation=10, color='b')plt.title('人数最多的星期', fontproperties='STsong', fontsize=20)plt.xlabel('时间', fontproperties='STsong', fontsize=16)plt.ylabel('客人数量', fontproperties='STsong', fontsize=16)plt.show()#进行程序的交互设计if __name__ == '__main__':a=input("请输入你想绘制的图形:(最欢迎的菜品/菜品类别统计/菜品收益统计/客人的饭量统计/黄金时段统计/月最火爆的天数统计/最火爆的周天数")if a == '最欢迎的菜品':print(dimension_counts(dish_famous))print('绘制完成!程序结束')sys.exit()elif a == '菜品类别统计':print(dimension_orders(dish_order))print('绘制完成!程序结束')sys.exit()elif a == '菜品收益统计':print(dimension_counts_money(dish_money_count))print('绘制完成!程序结束')sys.exit()elif a == '客人的饭量统计':print(dimension_dish_count(dish_order_count))print('绘制完成!程序结束')sys.exit()elif a == '黄金时段统计':print(dimension_time_count(time_count))print('绘制完成!程序结束')sys.exit()elif a == '月最火爆的天数统计':print(dimension_daycount(day_count))print('绘制完成!程序结束')sys.exit()elif a == '最火爆的周天数':print(dimension_weekcount(week_count))print('绘制完成!')sys.exit()else:print('输入错误,请输入括号内提示的图形种类')print('执行完毕,无图可画')sys.exit()