0%

2019泰迪杯数据分析技能赛B题心得

2019泰迪杯数据分析技能赛B题心得

虽说泰迪杯技能赛不太热门,但想要拿奖还是要花点时间。全称是泰迪杯数据分析职业技能大赛。重点在于数据处理与分析,比的是数据的洞察力和敏感程度。再辅以编程基础与搜索能力完成比赛。

在2019年,两道题分别是超市销售分析和校园卡消费分析。前者只可以通过编程解决,使用excel会扣分。但是我们可以通过excel来验证我们的想法,并将excel操作通过代码来实现。后者可以通过官方提供的数据分析工具解决也可以通过编程解决。但去年B题官方一边比赛,一边对其工具进行debug,体验不太友好。

要想获奖还要关注官方的线上辅导直播,特别是赛前的那几次。一般会明确赛题的导向和技术要点。比如因为前年技能赛,官方没有考虑到大家爬虫的威力,直接服务器被爬崩了,在去年的赛前直播中就谈到了暂时取消爬虫环节直接提供数据,这样可以减少一些不必要的付出。但是今年可能要注意,官网放出的竞赛内容中提到了数据采集与爬虫技术,以及数据保存。这个结尾再谈。

下面是我们小组完成A题的思路。
语言选择:python
使用库:pandas,numpy, matlibplot, wordcloud
代码:
GitHub:https://github.com/mmmistgun/Tipdm_Data_Analysis_II
Gitee:https://gitee.com/mistgun19/Tipdm_Data_Analysis_II
Gitea:http://esc.mistgun.cn:3000/marques/Tipdm_Data_Analysis_II
CodeChina: https://codechina.csdn.net/MISTGUN/tipdm_data_analysis_ii

读取官方数据

数据特点:

  1. 官方给的是csv文件,使用文本编辑器打开,可以发现其分隔符是“,”逗号,使用文本相关的库打开进行处理是不实际的。后期分离不同的数据操作比较耗时。
  2. 官方给的数据非常庞大,数据有7W多条,每条有9列。

方案一 openpyxl库

这是个适用于读写的excel文件的库,对于数据处理并不友善,读取和处理大数据集时间比较长。

方案二 pandas库

Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗功能。

数据读取方法:

1
2
3
import pandas as pd
data_csv = pd.read_csv(r"../result/附件.csv", encoding='gbk')
print("原始数据数量" + str(len(data_csv)))

数据预处理(数据清洗)

官方并不会明确要求具体进行哪些预处理操作,到在解题时是必不可少的一步。在进行书写报告时,数据与预处理的每一步,在必要时说明执行的目的,并对步骤的结果进行解释

数据去重

目的: 针对所有数据进行数据去重

1
2
# inplace=True 即直接对对象进行修改,否则操作不会保存,将结果返回
data_csv.drop_duplicates(inplace=True)

去除空值

目的:哈哈哈顾名思义

1
2
# how = 'any' 即去除所有的空值
data_csv = data_csv.dropna(how='any')

单位标准化

目的:减小精度对数据处理的干扰,故对数值进行标准化操作,保留五位小数;

1
data_csv["销售金额"] = data_csv["销售金额"].round(decimals=5)

数据合法性检测

  1. 日期合法性
    日期进行合法性验证,将日期转化为datetime类型,将非法日期剔除,最后使用去空值操作去除。
    1
    2
    3
    4
    # errors='coerce' 忽略不合法的值,置为null
    data_csv["销售日期"] = pd.to_datetime(data_csv["销售日期"],format='%Y%m%d',errors='coerce')
    print(data_csv.isnull().sum())
    data_csv = data_csv.dropna(how='any')
  1. 验证销售金额、单价和数量
    目的:销售金额与商品单价、销售数量的等式验证
    1
    2
    data_csv_check = data_csv[data_csv["是否促销"]=='否'].eval('应付减实付 =(商品单价*销售数量 - 销售金额)')
    print(data_csv_check[data_csv_check["应付减实付"] > 1]["大类名称"].value_counts())
    结果 结果解释:首先排除促销商品的干扰,再筛选应付金额与实付金额的差值大于1元的数据有369条,最后通过聚类分析发现,差值大的数据集中在蔬果大类。故推断为超市对保鲜期将到的商品进行降价处理或用户选择附加服务(如:购买塑料袋等),对此部分数据不进行处理。
  1. 删除商品总额为零的数据
    1
    data_csv = data_csv.drop(data_csv[data_csv["销售金额"] == 0].index)
    结果解释:通过筛选发现商品总额为零的商品为联营商品,故选择不进行统计操作,将此部分数据删除。

异常数据处理

目的:通过数据筛选发现存在商品单价与销售数量均为负数的数据,且可匹配到商品单价与销售数量均为其相反数的订单。 (在excel比对中发现)

1
2
3
xiaoshoujine_fushu = data_csv[data_csv["销售金额"] < 0]
xiaoshoushuliang_fushu = data_csv[data_csv["销售数量"] < 0]
print((xiaoshoujine_fushu == xiaoshoushuliang_fushu).sum())

结果解释:故推断为用户退货,将此部分数据删除;

1
2
3
4
5
6
for i in range (len(xiaoshoushuliang_fushu)):
data_csv.drop(data_csv[
(data_csv["顾客编号"] == list(xiaoshoushuliang_fushu["顾客编号"])[i]) &
(data_csv["小类名称"] == list(xiaoshoushuliang_fushu["小类名称"])[i]) &
(abs(data_csv["销售金额"]) == abs(list(xiaoshoushuliang_fushu["销售金额"])[i]))
].index, inplace=True)

数据冗余处理

数据冗余的主要办法是交叉验证

1
2
3
4
5
6
7
8
9
print("去冗余,交叉验证")
print(pd.crosstab(data_csv['小类编码'],data_csv["商品编码"],margins_name=True))
print("\n")
print(pd.crosstab(data_csv['小类编码'],data_csv["小类名称"],margins_name=True))
print(pd.crosstab(data_csv['中类编码'],data_csv["中类名称"],margins_name=True))
print(pd.crosstab(data_csv['大类编码'],data_csv["大类名称"],margins_name=True))

data_csv.to_csv(r"../result/task1_1.csv", index=False,index_label=False,encoding='gbk')
print("task1_1 completed")

结果解释:经过观察数据猜测商品编码与小类编码、小类编码与小类名称、中类编码与中类名称、大类编码与大类名称存在表达相同的特征值的情况。经过交叉验证,发现小类编码与小类名称、中类编码与中类名称、大类编码与大类名称存在表达相同的特征值的情况,商品编码与小类编码不存在表达相同的特征值的情况。

数据统计

这一步,官方给出了明确的要求,只要按部就班的照做就好。
赛题任务1
这道任务用的pandas库的DataFrame的基本操作加以阅读pandas官方文档并理解,即可完成。

  1. 对于任务1.2编写函数,以“大类名称”字段名为索引,计算各大类商品总的销售金额。
  2. 对于任务1.3,仍然编写函数,以“中类名称”字段名为索引,将每个中类商品的促销销售金额和非促销销售金额统计进行直接筛选统计保存数据
  3. 对于任务1.4,生鲜类产品和一般产品的每周销售金额采取根据日期相对应的在一年中的周数打标签,再进行筛选,通过调用数据透视表函数进行销售额累加,最终生成新表;
  4. 对于任务1.5,编写筛选函数,将每位顾客每月的消费额及消费天数统计,首先按月分组消费数据,再通过程序对各月的顾客编号与销售金额、顾客编号与购买次数建立透视表,最后对数据进行整合保存。

数据分析与可视化

这一步,不仅仅是pandas与numpy库的运用,还有使用matlibplot库进行绘图。
赛题任务2

  1. 对于任务2.1,首先将数据对商品类型进行筛选分为生鲜类和一般商品类,再使用透视表统计隔日销售额,最后调用相关绘图函数,完成绘图;
  2. 对于任务2.2,首先按销售月份筛选数据,再按照大类名称建立与销售金额的透视表,最后完成绘图;
  3. 对于任务2.3,首先通过是否促销进行数据筛选,再获取当前日期所对应的在一年之中对应的周数,分别建立周数与销售金额的透视表,完成绘图;

用户画像与策略

用户画像我们使用了wordcloud词云进行绘制虽然不够美观但是表示还是清晰的
赛题任务3

  1. 对于任务3.1,以顾客编号为筛选条件,对用户消费金额获取透视表,并进行排序取前10名顾客的用户编号,再获取这十名顾客的消费详情,根据金额绘制用户画像,根据消费金额比重绘制用户画像,总体上均可看出一个消费者的消费喜好。
  2. 对于任务3.2,根据各大类名对数据进行筛选,具体为获取总表DataFrame的各大类名然后去重获取不同类名;然后根据类名对数据进行分割,获取各个类对应的数据。最后对每个类每天各自的每日销售量和销售总额分别进行进行汇总得到新的数据源。根据新数据源进行绘图。
  3. 对于任务3.3,以大类名称为标签索引,通过计算促销商品的日均销售额(促销商品总额/进行促销的总天数)与非促销商品的日均销售额(非促销商品总额/进行促销的总天数)得出他们的柱状对比图。

结束语

如果有哪里没写对,没写好的地方,欢迎提出,一起探讨。对于后面几道主观题的结果还是不进行分享了。主要分享一下解题的思路,说不定大家有更好的答案,题目、每个任务的代码、过程数据和结果放在了开头的代码仓库。这次技能赛,虽说没能到达最后的答辩,争取泰迪杯。但是在赛前一天就速通pandas和numpy的各种函数与操作,比赛当天一起百度,查库函数的官方文档,还能拿到一等,回想起来还是很刺激。感谢波神和昌洲大佬。合作愉快^_^!

题外话

今年似乎爬虫又回归了,根据参加第一届数据挖掘比赛的同学和师兄回忆,第一届的时候,官方给出的是一个的网站,大家需要自行编写爬虫,爬取所需要的信息。也可以自己额外爬取其他网站增加数据。从我第一感觉上来说,理论上是应该不会有反爬的操作,要不然这比赛也太刺激了吧。要自行编写爬虫,这就意味着参赛的同学,要对网页结构有初步的理解。这个可以百度下html了解一下,上手难度不会太大。按照我以往的编写爬虫经验,给出一些的好用的库参考下吧。

  1. 方案一: scrapy爬虫框架
    强大的爬虫框架,功能强大,需要一定的时间上手。最好能理解架构。

  2. 方案二: requests + BeautifulSoup + 正则表达式
    这个方案是我最熟悉的一个方案,
    requests库 负责完成网页请求,获取网页信息。
    对于反爬,可以加上headers,proxy,cockies等必要信息,控制访问频率,来应对反爬虫,使你的行为更像真实用户
    在没有反爬虫时或者反爬虫技术失效时,可以采用多进程,提高爬虫效率,不建议对正常运行的网站这么做,会给网站运维和其他访问用户增加压力。一些网站会在网站上添加robots.txt,告知对应的爬虫被允许的权限。当然这也是君子协定哈哈。
    BeautifulSoup库 负责完成请求结构解析,并以树的形式进行封装,方便用户索引。
    正则表达式则是在BeautifulSoup库,不好用的时候,直接进行文本匹配,暴力获取的方法。

  3. 方案三:八爪鱼采集器
    一款爬虫软件,一站式服务,不用自己编程,但是有些功能需要人民币才能解决。

    手动滑稽

对于数据存储这一块,为了简单的话,可以考虑存成csv,或者说excel表格,python自带csv库,写是挺方便的。
有能力的话可以考虑数据库,常用的SQL语言也就四句(增删改查):insert, update, delete, select

欢迎关注我的其它发布渠道