Python-2018年“泰迪杯“数据分析职业技能大赛B题任务二-个人代码分享[完整更新版]

前言

抱歉拖了很长时间都没更新,这个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 task1

def 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) # 设置标题,字体为18pt
    ax.set_ylabel(ylabel_, fontsize=18) # 设置y轴,字体为18pt
    ax.set_xlabel(xlabel_, fontsize=18)  # 设置x轴,字体为18pt
    plt.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 saleMonthDict
        saleMonthDict = {}  # 创建一个空字典
        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到9
            lst = [] # 创建一个空的临时字典
            for j in range(1, calendar.monthrange(2017, i)[1]+1): # 从1遍历到对应月份的最后一天
                lst1 = [] # 创建一个空的临时字典
                for k in range(0,24): # 循环一天24小时中0到23
                    num = 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': # 判断工作路径最后的子文件夹是否为program
    os.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题任务一-个人代码分享】

数据集代表了新泽西州中部各个地点的售货机数据。这些地点包括图书馆、商场、办公地点和制造地点,可以利用数据来了解不同地点的用户行为、整体偏好和趋势。 售货机的位置信息如下: (1) Gutten Plans:一家 24小时/5天 营业的冷冻面团专业公司。分配的售货机是:GuttenPlans x 1367 (2) EB 公共图书馆:每周5-6天有大量人流的公共图书馆。分配的售货机是:EB Public Library x1380 (3) Brunswick 广场商场:每周7天有平均人流量的商场。分配的售货机是:BSQ Mall x1364 - Zales,BSQ Mall x1366 - ATT (4) Earle Asphalt:一家每周5天营业的建筑工程公司。分配的售货机是:Earle Asphalt x1371 数据说明 字段 说明 Status 代表机器数据是否被成功处理 Device ID 唯一电子标识符(也称为ePort)用于售货机每台机器分配一个唯一的ePrt设备 Location 表示售货机的位置 Machine 用户友好的机器名称 Product 从机器售出的产品 Category 碳酸饮料/食物/非碳酸饮料/水 Transaction 每次交易的唯一标识符 TransDate 交易的日期和时间 Type 交易类型(现金/信用) RCoil 用于售出产品的线圈号# RPrice 产品的价格 RQty 已售数量。这通常为1,但机器可以配置为在一次交易中售出更多商品 MCoil 用于售出产品的映射线圈号#(来自toucan) MPrice 产品的映射价格 MQty 已售映射数量。这通常为1,但机器可以配置为在一次交易中售出更多商品 LineTotal 每次交易的销售 TransTotal 表示将在信用卡上显示的所有交易的计。用户可以以3美元售出一份饮料和1.5美元一份小吃,共4.50美元 Prcd Date SeedLive(用于电子汇所有交易的实体)处理交易的日期
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值