1.数据分析概述
1.1 本章内容
本案例数据为招聘网站上收集的有关数据分析师岗位的数据,对该数据集从数据分析的角度出发,利用pandas、pyecharts库处理与展现数据,开发一个完整的数据分析项目。
1.2 什么是数据分析
数据分析是指运用适当的统计分析方法对收集的大量数据进行分析,将这些数据加以汇总和理解并消化,以实现最大化地开发数据的功能,发挥数据的作用。
1.3 数据分析的流程
1.4 使用pyecharts绘制图表
大部分数据是以文本或数值的形式显示的,这种形式的数据不仅让人感觉十分枯燥,而且无法让人直观地看到其中的关系和规律。
为帮助用户快速地从数据中捕获信息,可以用图表形式的数据替代诸如文本或数值形式的数据,更好地给人们传递数据内部潜在的信息。
1.4.1 pyecharts简介
pyecharts官网有很多案例,如果使用pyecharts,可以在官网中找到相关配置
✨ 特性
简洁的 API 设计,使用如丝滑般流畅,支持链式调用
囊括了 30+ 种常见图表,应有尽有
支持主流 Notebook 环境,Jupyter Notebook 和 JupyterLab
可轻松集成至 Flask,Django 等主流 Web 框架
高度灵活的配置项,可轻松搭配出精美的图表
详细的文档和示例,帮助开发者更快的上手项目
多达 400+ 地图文件以及原生的百度地图,为地理数据可视化提供强有力的支持
1.4.2安装pyecharts
pip install pyecharts==1.9.0
1.4.3 pyecharts绘制图表过程
使用pyecharts绘制各种图表的过程大致相同,一般可分为4步:
创建图表类对象
添加图表数据与系列配置项
添加图表全局配置项
渲染图表
1 创建图表类对象
pyecharts库支持绘制30+个丰富的Echarts 图表,它针对每个图表均提供了相应的类,并将这些图表类封装到pyecharts.charts模块中。
前表中列举的类均代表一个常见的图表,它们可使用与类同名的构造方法创建图表实例。
Line(init_opts=opts.InitOpts())
init_opts:表示初始化配置项,该参数需要接收一个InitOpts类的对象,通过构建的InitOpts类对象可以为图表指定一些通用的属性,比如背景颜色、画布大小等。
构建示例
line_demo = Line(init_opts=opts.InitOpts(theme=ThemeType.ROMA))
2 添加图表数据与系列配置项
系列配置项是一些针对图表特定元素属性的配置项,包括图元样式、文本样式、标签、线条样式、标记样式、填充样式等,其中每个配置项都对应一个类。
使用add_xaxis()、add_yaxis()或add()方法可以添加图表数据或系列配置项。
add_yaxis(self, series_name, y_axis, is_selected=True, is_connect_nones=False, xaxis_index=None, yaxis_index=None, color=None, is_symbol_show=True, symbol=None, symbol_size=4, ...)
y_axis:表示系列数据。
symbol:表示标记,可以接收的取值有‘circle’(圆形)、‘rect’(矩形)、‘roundRect’(圆角矩形)、‘triangle’(三角形)、‘diamond’(菱形)、‘pin’(大头针)、‘arrow’(箭头)、‘none’(无)。
symbol_size:表示标记的大小。
为前面创建的line_demo对象添加一组数据,并设置折线图的标记为菱形、标记大小为10。
line_demo.add_yaxis('', jobs_count.values.tolist(), symbol='diamond',symbol_size=10)
3 添加图表全局配置项
全局配置项是一些针对图表通用属性的配置项,包括初始化属性、标题组件、图例组件、工具箱组件、视觉映射组件、提示框组件、数据区域缩放组件,其中每个配置项都对应一个类。
若pyecharts需要为图表设置全局配置项(InitOpts除外),则需要将全局配置项传入set_global_options()方法中。
set_global_opts(self, title_opts=opts.TitleOpts(), legend_opts=opts.LegendOpts(), tooltip_opts=None, toolbox_opts=None, brush_opts=None, xaxis_opts=None, yaxis_opts=None, visualmap_opts=None, datazoom_opts=None, graphic_opts=None, axispointer_opts=None)
title_opts:表示标题组件的配置项,接收一个TitleOpts类的对象;
yaxis_opts:表示y轴的配置项,接收一个AxisOpts类的对象。
4. 渲染图表
图表可通过两种方法进行渲染:render()和render_notebook(),其中render()方法用于将图表渲染到HTML文件;render_notebook()方法用于将图表渲染到Jupyter Notebook工具中。
line_demo.render_notebook()
2. 分析目标与思路
目标驱使行动,行动决定思路。在项目伊始期间,我们需要明确项目的目标,只有明确了目标
,才能保证后期的行为不会偏离方向,否则得出的分析结果将没有任何指导意义。
2.1 分析目标
分析数据分析师岗位的需求趋势
分析数据分析师岗位的热门城市Top10
分析不同城市数据分析师岗位的薪资水平
分析数据分析师岗位的学历要求
在明确了分析目标之后,我们需要将项目目标分解到数据分析的各个环节,方便开发人员清楚自己在各环节应该开展哪些工作。
2.2 数据收集
熟悉数据收集的工作内容,可以熟练地使用pandas库读取文件中的数据,并筛选与分析目标关联紧密的列数据。
在开发项目之前,我们需要提前准备好分析的数据。这里直接使用从天池网站上下载的一份有关数据分析师岗位的数据(从2019年11月初到12月初),分别将这些数据保存至lagou01.csv和lagou02.xlsx文件中。数据集下载地址
观察两张表格可知,两张表格中有多列标题相同的数据,但并非每列数据都与数据分析目标有关,这里只需要保留与数据分析目标相关的部分列数据即可。
2.21 导入模块:
import time import pandas as pd from pyecharts.charts import Bar, Line, Pie from pyecharts import options as opts from pyecharts.globals import SymbolType, ThemeType
2.2.2 导入数据
读取lagou01.csv文件的数据
# 读取lagou01.csv文件的数据 recruit_obj = pd.read_csv('lagou01.csv', encoding='gbk') # 过滤与分析目标无关的数据,保留有关的数据 new_df_01 = pd.DataFrame([recruit_obj['city'], recruit_obj['companyFullName'], recruit_obj['salary'], recruit_obj['companySize'], recruit_obj['district'], recruit_obj['education'], recruit_obj['firstType'], recruit_obj['positionAdvantage'], recruit_obj['workYear'], recruit_obj['createTime']]).T new_df_01
输出为:
读取lagou02.xlsx文件的数据
# 读取lagou02.xlsx文件的数据 recruit_obj2 = pd. read_excel('lagou02.xlsx',engine='openpyxl') new_df_02 = pd.DataFrame( [recruit_obj2['city'], recruit_obj2['companyFullName'], recruit_obj2['salary'], recruit_obj2['companySize'], recruit_obj2['district'], recruit_obj2['education'], recruit_obj2['firstType'], recruit_obj2['positionAdvantage'], recruit_obj2['workYear'], recruit_obj2['createTime']]).T new_df_02
输出为:
转换时间格式
# 转换时间格式 new_df_01['createTime'] = pd.to_datetime(new_df_01['createTime']) new_df_02['createTime'] = pd.to_datetime(new_df_02['createTime']) new_df_01.head()
输出为:
采用上下堆叠的方式合并数据
# 采用上下堆叠的方式合并数据 final_df = pd.concat([new_df_01, new_df_02], ignore_index=True) # 给final_df重新设置列索引的名称 final_df = final_df.rename(columns={'city':'城市', 'companyFullName':'公司全称', 'salary':'薪资', 'companySize':'公司规模', 'district':'区', 'education':'学历', 'firstType':'第一类型', 'positionAdvantage':'职位优势', 'workYear':'工作经验', 'createTime':'发布时间'}) final_df
输出为:
2.3 数据预处理
尽管从网站上采集的数据是比较规整的,但可能会存在着一些问题,无法直接被应用到数据分析中。为增强数据的可用性,我们需要对前面准备的数据进行一系列的数据清理操作,包括检测与处理重复值、检测与处理缺失值。
2.3.1. 查看数据的整体信息
final_df.info()
输出为:
<class 'pandas.core.frame.DataFrame'> RangeIndex: 3143 entries, 0 to 3142 Data columns (total 10 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 城市 3142 non-null object 1 公司全称 3142 non-null object 2 薪资 3142 non-null object 3 公司规模 3142 non-null object 4 区 3135 non-null object 5 学历 3142 non-null object 6 第一类型 3142 non-null object 7 职位优势 3142 non-null object 8 工作经验 3142 non-null object 9 发布时间 3142 non-null datetime64[ns] dtypes: datetime64[ns](1), object(9) memory usage: 245.7+ KB
info返回结果分析如下:
由于整组数据中没有数值类型的数据,所以这里不再检测异常值,而只需要检测与处理重复值、缺失值即可。
2.3.2 重复值处理
# 检测重复值 final_df[final_df.isna().values==True]
输出为: