本文主要是介绍Python-2018年“泰迪杯“数据分析职业技能大赛B题任务二-个人代码分享[完整更新版],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
用python完成泰迪杯B题的任务二
- 前言
- 1.问题重述
- 2.问题分析
- 3.问题的求解
- 4.代码展示
- 5.结果展示
- 6.对代码的一些注释
- 后语
前言
抱歉拖了很长时间都没更新,这个2018年泰迪杯B题的任务是本人决定在第二次Python课程的考核项目,做完了迟迟没放上来先说声抱歉。。。
1.问题重述
题目源文件:https://pan.baidu.com/s/1HZvjMo9ct5nG5FYqzcta4Q
- 任务 2.1 绘制 2017 年 6 月销量前 5 的商品销量柱状图。
- 任务 2.2 绘制每台售货机每月总交易额折线图及交易额月环比增长率柱
状图。- 任务 2.3 绘制每台售货机毛利润占总毛利润比例的饼图(假设饮料类毛
利率为 25%,非饮料类为 20%)。- 任务 2.4 绘制 4 月每台售货机交易额与订单量气泡图,横轴为售货机编
号,纵轴为月订单量。- 任务 2.5 绘制售货机 C 6、7、8 三个月订单量的热力图,横轴以天为单
位,纵轴以小时为单位。从热力图可以分析得出哪些结论?
2.问题分析
- 针对任务2.1,要重新对数据进行处理,得到一个只有六月份的销售记录再进行处理。
- 针对任务2.2,直接使用前面任务1.3的数据,每月的数据都要乘上相对应的天数才能进行使用。
- 针对任务2.3,需要将附件2中的大类和二级类添加到原来的销售记录形成新的销售记录进行处理才能计算,因此会有读取附件2的操作,然后就是利用自己写的一种饼状图函数来绘制出饼状图。
3.问题的求解
任务二会承接之前任务一的代码(详情可见Python-2018年"泰迪杯"数据分析职业技能大赛B题任务一-个人代码分享[代码已更新]),任务2.1要重新做数据处理;任务2.2可以直接调用task1的数据;任务2.3是对数据进行标签的结合形成新的数据,再利用新的数据进行分析。最后调用第三方库的matplotlib的子模块pyplot来进行可视化处理。
注意!这里的matplotlib.pyplot是第三方模块,原生的python编辑器上并没有安装该模块,需要自行pip安装,嫌麻烦的小伙伴可以用Anaconda运行,Anaconda一般都包含比较热门的第三方模块,其中就用有matplotlib.pyplot模块。
4.代码展示
# -*- coding=utf-8 -*-
# 导入模块
import os
import re
import calendar
import numpy as np
import seaborn as sns
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from task1 import task1def Bar(title_, xlabel_, ylabel_, x, y, label_): # 定义柱状图函数matplotlib.rcParams['axes.unicode_minus'] = False # 使图像中负号正确生成plt.rcParams['font.sans-serif']=['simHei']#用simHei字体显示图像的中文标签plt.title(title_) # 设置图像标题plt.xlabel(xlabel_) # 设置x轴标签说明plt.ylabel(ylabel_) # 设置y轴标签说明plt.bar(x, y, label=label_, width=0.2) # 调用bar柱状图函数# plt.show() # 显示图像def Plot(title_, label_, xlabel_, ylabel_, x, y): # 定义折线图函数matplotlib.rcParams['axes.unicode_minus'] = False # 使图像中负号正确生成plt.rcParams['font.sans-serif'] = ['simHei'] # 使用simHei字体让图像的中文正常显示plt.title(title_) # 设置图像标题plt.xlabel(xlabel_) # 设置x轴标签说明plt.ylabel(ylabel_) # 设置y轴标签说明plt.plot(x, y, label=label_) # 调用plot折线图函数# 为了形成五台销售机月销售额的折线都在同一张图上,将以下单张显示图片的代码进行注释# plt.legend()# plt.show()def Pie(x, labels_, title_): # 定义饼状图函数matplotlib.rcParams['axes.unicode_minus'] = False # 使图像中负号正确生成plt.rcParams['font.sans-serif']=['simHei'] # 使用simHei字体让图像的中文正常显示plt.title(title_) # 设置图像标题plt.pie(x = x, labels = labels_, autopct='%.4f%%') # 调用饼状图函数plt.show() # 显示图像def Scatter(tem, rain, size, title, xlabel_, ylabel_): # 定义气泡图的函数matplotlib.rcParams['axes.unicode_minus'] = False # 使图像中负号正确生成colors = np.random.rand(len(tem)) # 使用random库生成随机颜色plt.ylim([300,1000]) # 设置y轴限制上下限plt.xlabel(xlabel_) # 设置x轴标签plt.ylabel(ylabel_) # 设置y轴标签plt.scatter(tem, rain ,s=size, c=colors, alpha=0.6) # 掉用matplotlib中的气泡图函数plt.show() # 显示图像def Heatmap(array, columns_, title_, xlabel_, ylabel_): # 定义热力图的函数matplotlib.rcParams['axes.unicode_minus'] = False # # 使图像中负号正确生成plt.rcParams['font.sans-serif'] = ['simHei'] # 用simHei字体显示图像的中文标签fig, ax = plt.subplots(figsize=(9, 9))# 二维的数组的热力图,横轴和数轴的ticklabels要加上去的话,既可以通过将array转换成有column# 和index的DataFrame直接绘图生成,也可以后续再加上去。后面加上去的话,更灵活,包括可设置labels大小方向等。sns.heatmap(pd.DataFrame(array, columns=columns_, index=range(0, 24)),annot=True, vmax=array.max(), vmin=array.min(), xticklabels=True, yticklabels=True, square=False, cmap="YlGnBu")ax.set_title(title_, fontsize=18) # 设置标题,字体为18ptax.set_ylabel(ylabel_, fontsize=18) # 设置y轴,字体为18ptax.set_xlabel(xlabel_, fontsize=18) # 设置x轴,字体为18ptplt.show()class task2:"""创建有关任务2代码的类"""classList = ['A', 'B', 'C', 'D', 'E'] # 定义销售机标签列表MonthList = [str(i)+'月' for i in range(1,13)] # 定义月份列表def Sys1(self): # 创建任务2.1的方法dataList = task1.data('附件1.csv') # 调用task1中task1类的data方法获取数据列表nameList = [i[4] for i in dataList] # 遍历dataList将每一条记录的名字添加进列表numDict = {}.fromkeys(set(nameList), 0) # 生成一个以销售名字为键,初始值为0的字典for i in dataList: # 遍历数据列表if re.match('2017/6/', i[5]) != None: # 判断是否符合2017年6月的格式字符串numDict[i[4]] += 1 # 字典中的销售名字对应的值加1# 利用排序函数,通过映射来将字典中的销售名字按照值来进行排序并获取前五个元组,返回形成一个字典topFiveDict = dict(sorted(numDict.items(), key=lambda d:d[1], reverse=True)[0:5])# 调用绘制柱状图函数Bar('2017年6月销量前5的商品销量柱状图', '商品名', '销售量/件', topFiveDict.keys(), topFiveDict.values(), '')plt.show()# print(topFiveDict)def Sys2(self): # 创建任务2.2的方法global saleMonthDictsaleMonthDict = {} # 创建一个空字典for i in self.classList: # 遍历销售机标签列表dataList = task1.data(r'result\task1-1' + i + '.csv')[:-1] # 调用数据处理方法month = 0 # 定义变量初始值lst = [] # 创建一个空的临时列表for k in range(12): # 循环12次month += 1 # 对月份进行累加sale, num = task1.datacount(dataList[1:], '2017/' + str(month) + '/') # 调用数据计算方法saleMonth, numMonth = round(sale, 3), round(num, 3) # 对获得的数据进行计算lst.append((saleMonth, numMonth)) # 将计算的数据通过元组形式添加进临时列表saleMonthDict[i] = lst # 将临时列表作为元素添加进对应的销售机标签的值print(saleMonthDict)for x in self.classList: # 遍历销售机标签列表y = [i[0] for i in saleMonthDict[x]] # 将销售记录字典中对应销售机的每月总交易额提取出来形成列表Plot('五台销售机每月总交易额折线图', x+'销售机', '月份/月', '交易额/元', self.MonthList, y) # 调用画折线图函数plt.legend() # 现实图像标签plt.show() # 现实图像saleUpDict = {} # 创建一个空字典for x in self.classList: # 遍历标签列表lst = [] # 创建一个空的临时列表for i in range(1,12): # 从1到11遍历11次a = (saleMonthDict[x][i][0] - saleMonthDict[x][i-1][0])/saleMonthDict[x][i-1][0] # 对月环比进行计算lst.append(round(a,3)) # 取数字的小数点后三位,添加进临时列表中saleUpDict[x] = lst # 创建销售机标签-临时列表键值对添加进列表# print(saleUpDict)width = -0.2 # 定义初始绘制的柱状图在刻度的左两格处for x in self.classList: # 遍历销售机标签列表lst = np.arange(len(self.MonthList[1:]))# 调用绘制柱状图函数Bar('五台销售机每月增长率柱状图', '月份/月', '月环比增长率', lst+width, saleUpDict[x], x+'销售机') # 调用画柱状图函数width += 0.2 # 宽度进行累加plt.xticks([i+0.2 for i in range(len(self.MonthList[1:]))], self.MonthList[1:]) # 重新设置x轴刻度plt.legend() # 显示图标plt.show() # 显示图像def Sys3(self): # 创建任务2.3的方法dataList = task1.data('附件2.csv')[1:] # 调用数据处理方法firstClassList = [i[1] for i in dataList] # 获取大类标签列表nameList = [i[0] for i in dataList] # 获取名字列表nameClassDict = dict(zip(nameList, firstClassList)) # 将名字-大类打压成字典firstClassSet = sorted(set(firstClassList), key=lambda d:len(d)) # 利用排序函数来固定饮料,非饮料的排序列表,同时去重classDict = {} # 创建一个空字典for x in self.classList: # 遍历销售机标签列表dataList1 = task1.data(r'result\task1-1'+x+'.csv')[:-1] # 调用数据处理方法lst = [] # 创建一个临时列表for i in firstClassSet: # 遍历大类标签列表a = 0 # 定义一个初始值为0的变量for j in dataList1[1:]: # 遍历销售记录列表if nameClassDict[j[4]] == i: # 如果销售记录中名字对应的大类标签等于x,则进行实际金额的累加a += round(float(j[3]), 1)lst.append(round(a,1)) # 将金额取小数点后1一位然后添加进临时列表里classDict[x] = lst # 将销售机对应的临时列表两大类的总实际金额创建成键值对添加进字典中maoSale = [(round(i[0]*0.25, 3), round(i[1]*0.2, 3)) for i in classDict.values()] # 对两大类进行毛利润计算drinkList, notDrinkList = [i[0] for i in maoSale], [i[1] for i in maoSale] # 将饮料、非饮料的毛利润提取出来形成列表# print(drinkList, notDrinkList)drink, notDrink = 0, 0 # 定义两个初始值为0的变量for i in range(5): # 循环5次drink += drinkList[i] # 对饮料的毛利润进行累加notDrink += notDrinkList[i] # 对非饮料的毛利润进行累加drink, notDrink = round(drink, 3), round(notDrink, 3) # 对两个累加值取小数点后3位数字处理drinkPerList = [round(i/drink, 5) for i in drinkList] # 将饮料类的毛利润列表进行计算百分比形成列表notDrinkPerList = [round(i/notDrink, 5) for i in notDrinkList] # 将非饮料类的毛利润列表进行百分比计算形成列表# print(drinkPerList, notDrinkList)classList = [i+'售货机' for i in self.classList]Pie(drinkPerList, classList, '五台售货机饮料类毛利润占总毛利润的比例饼状图') # 调用画饼状图函数Pie(notDrinkPerList, classList, '五台售货机非饮料类毛利润占总毛利润的比例饼状图') # 调用画饼状图函数def Sys4(self): # 创建任务2.4的方法aprilSaleList = [i[3][0] for i in saleMonthDict.values()] # 获取五台销售机4月销售额的列表aprilNumList = [i[3][1] for i in saleMonthDict.values()] # 获取五台销售机4月销售量的列表# print(aprilSaleList, aprilNumList)# 调用画气泡图的函数Scatter(self.classList, aprilNumList, aprilSaleList, '4月每台售货机交易额与订单量气泡图', '销售机编号', '月订单量')def Sys5(self): # 创建任务2.5的方法global CDayDict # 全局变量dayDict = {} # 创建一个空的日期字典for i in range(6, 9): # 循环6月到8月,3次dayList = [] # 创建一个空的临时列表for j in range(1, calendar.monthrange(2017, i)[1]+1): # 遍历i月中含有的天数dayList.append('%s月%s日' % (i, j)) # 使用格式字符串,将日期添加进临时列表中dayDict[i] = dayList # 将日期列表以及其对应的月份创建成键值对添加进字典中dataList = task1.data(r'result\task1-1C.csv')[:-1] # 调用task1中的数据处理方法# 用匹配字符串来获取6、7、8月C销售机的销售记录juneList = [i for i in dataList[1:] if re.match('2017/6', i[5]) != None]julyList = [i for i in dataList[1:] if re.match('2017/7', i[5]) != None]mayList = [i for i in dataList[1:] if re.match('2017/8', i[5]) != None]CDict = dict(zip([6, 7, 8], [juneList, julyList, mayList])) # 将对应的销售记录和月份创建成键值对添加进字典CDayDict = {} # 创建C销售机每天的销售量字典for i in range(6,9): # 遍历6到9lst = [] # 创建一个空的临时字典for j in range(1, calendar.monthrange(2017, i)[1]+1): # 从1遍历到对应月份的最后一天lst1 = [] # 创建一个空的临时字典for k in range(0,24): # 循环一天24小时中0到23num = 0 # 定义一个初始值为0的变量for x in CDict[i]: # 遍历对应月份的销售记录if re.match('2017/%s/%s %s:'%(i,j,k), x[5]) != None: # 判断是否符合格式字符串num += 1 # 对变量进行累加计数lst1.append(num) # 将每小时的订单量添加进列表lst.append(lst1) # 将每天每小时订单量添加进列表CDayDict[i] = lst # 将最终得到的二维列表按照对应月份添加进字典中for i in range(6,9): # 遍历6到9# 调用热力图函数Heatmap(np.array(CDayDict[i]).transpose(), dayDict[i], 'C销售机%s月订单量的热力图'%i, '天数', '小时/h')def __init__(self):# 调用类中的方法task2.Sys1(self)task2.Sys2(self)task2.Sys3(self)task2.Sys4(self)task2.Sys5(self)if os.getcwd()[-7:] == 'program': # 判断工作路径最后的子文件夹是否为programos.chdir(os.path.dirname(os.getcwd())) # 获取目标工作路径,删除最后的子文件夹并重新作为工作目录if not os.path.exists('result'): # 判断 result 文件夹是否存在,若不存在,则创建 result 文件夹os.mkdir('result')task2 = task2()
5.结果展示
6.对代码的一些注释
为什么下面主程序开始的地方要加入这样一个文件操作?
因为泰迪杯B题的要求是将附件1和程序放进program文件夹里面,生成的结果文件放进同program等级的result文件夹,因此才需要这样一个文件目录的操作。
后语
因为还会持续更新,所以就不多废话了,后续的三个任务再慢慢做吧,快到期末考试了,大家加油!(⊙︿⊙) - 2020.1.2
关于任务2.3的代码,其实说实话我不太清楚是不是这样做,如果有错误的希望大家指出我的错误,同时这也是过年之后的第一次小更,喜欢的话点个赞/关注,这是对我的最大支持,抱歉祝福晚了,祝大家新年快乐,元宵节快乐!(▽) - 2020.2.8
【Python-2018年"泰迪杯"数据分析职业技能大赛B题任务一-个人代码分享】
这篇关于Python-2018年“泰迪杯“数据分析职业技能大赛B题任务二-个人代码分享[完整更新版]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!