Main Takeaway
暑研期间主要做的就是数据分析的事情,那当然离不了python数据分析三件套了——在此记录三件套的基础学习(多用实践才能记住)
从原始数据中抽取出有价值的信息的这个过程我们就称之为数据分析,它是数据科学工作的一部分。
数据分析相关库
使用 Python 从事数据科学相关的工作是一个非常棒的选择,因为 Python 整个生态圈中,有大量的成熟的用于数据科学的软件包(工具库)。而且不同于其他的用于数据科学的编程语言(如:Julia、R),Python 除了可以用于数据科学,能做的事情还很多,可以说 Python 语言几乎是无所不能的。
三大神器
- NumPy:支持常见的数组和矩阵操作,通过
ndarray类实现了对多维数组的封装,提供了操作这些数组的方法和函数集。由于 NumPy 内置了并行运算功能,当使用多核 CPU 时,Numpy会自动做并行计算。 - Pandas:pandas 的核心是其特有的数据结构
DataFrame和Series,这使得 pandas 可以处理包含不同类型的数据的负责表格和时间序列,这一点是NumPy的ndarray做不到的。使用 pandas,可以轻松顺利的加载各种形式的数据,然后对数据进行切片、切块、处理缺失值、聚合、重塑和可视化等操作。 - Matplotlib:matplotlib 是一个包含各种绘图模块的库,能够根据我们提供的数据创建高质量的图形。此外,matplotlib 还提供了 pylab 模块,这个模块包含了很多像 MATLAB 一样的绘图组件。
1 | import numpy as np |
其他相关库
- SciPy:完善了 NumPy 的功能,封装了大量科学计算的算法,包括线性代数、稀疏矩阵、信号和图像处理、最优化问题、快速傅里叶变换等。
- Seaborn:seaborn 是基于 matplotlib 的图形可视化工具,直接使用 matplotlib 虽然可以定制出漂亮的统计图表,但是总体来说还不够简单方便,seaborn 相当于是对 matplotlib 做了封装,让用户能够以更简洁有效的方式做出各种有吸引力的统计图表。
- Scikit-learn:scikit-learn 最初是 SciPy 的一部分,它是 Python 数据科学运算的核心,提供了大量机器学习可能用到的工具,包括:数据预处理、监督学习(分类、回归)、无监督学习(聚类)、模式选择、交叉检验等。
- Statsmodels:包含了经典统计学和经济计量学算法的库。
Numpy的应用
Numpy 是一个开源的 Python 科学计算库,用于快速处理任意维度的数组。Numpy 支持常见的数组和矩阵操作,对于同样的数值计算任务,使用 NumPy 不仅代码要简洁的多,而且 NumPy 的性能远远优于原生 Python,基本是一个到两个数量级的差距,而且数据量越大,NumPy 的优势就越明显。
Numpy 最为核心的数据类型是ndarray,使用ndarray可以处理一维、二维和多维数组,该对象相当于是一个快速而灵活的大数据容器。NumPy 底层代码使用 C 语言编写,解决了 GIL 的限制,ndarray在存取数据的时候,数据与数据的地址都是连续的,这确保了可以进行高效率的批量操作,远远优于 Python 中的list;另一方面ndarray对象提供了更多的方法来处理数据,尤其是和统计相关的方法,这些方法也是 Python 原生的list没有的
创建数组对象
数组对象的属性
1 | size,shape,dtype,ndim,base |
数组的运算
表1:通用一元函数
| 函数 | 说明 |
|---|---|
abs / fabs | 求绝对值的函数 |
sqrt | 求平方根的函数,相当于array ** 0.5 |
square | 求平方的函数,相当于array ** 2 |
exp | 计算\(e^x\)的函数 |
log / log10 / log2 | 对数函数(e为底 / 10为底 / 2为底) |
sign | 符号函数(1 - 正数;0 - 零;-1 - 负数) |
ceil / floor | 上取整 / 下取整 |
isnan | 返回布尔数组,NaN对应True,非NaN对应False |
isfinite / isinf | 判断数值是否为无穷大的函数 |
cos / cosh / sin | 三角函数 |
sinh / tan / tanh | 三角函数 |
arccos / arccosh / arcsin | 反三角函数 |
arcsinh / arctan / arctanh | 反三角函数 |
rint / round | 四舍五入函数 |
表2:通用二元函数
| 函数 | 说明 |
|---|---|
add(x, y) / substract(x, y) | 加法函数 / 减法函数 |
multiply(x, y) / divide(x, y) | 乘法函数 / 除法函数 |
floor_divide(x, y) / mod(x, y) | 整除函数 / 求模函数 |
allclose(x, y) | 检查数组x和y元素是否几乎相等 |
power(x, y) | 数组\(x\)的元素\(x_i\)和数组\(y\)的元素\(y_i\),计算\(x_i^{y_i}\) |
maximum(x, y) / fmax(x, y) | 两两比较元素获取最大值 / 获取最大值(忽略NaN) |
minimum(x, y) / fmin(x, y) | 两两比较元素获取最小值 / 获取最小值(忽略NaN) |
dot(x, y) | 点积运算(数量积,通常记为\(\cdots\),用于欧几里得空间(Euclidean space)) |
inner(x, y) | 内积运算(内积的含义要高于点积,点积相当于是内积在欧几里得空间$\(的特例,而内积可以推广到**赋范向量空间**,只要它满足平行四边形法则即可) | | `cross(x, y) ` | 叉积运算(向量积,通常记为\)\(,运算结果是一个向量) | | `outer(x, y)` | 外积运算(张量积,通常记为\)$,运算结果通常是一个矩阵) |
intersect1d(x, y) | 计算x和y的交集,返回这些元素构成的有序数组 |
union1d(x, y) | 计算x和y的并集,返回这些元素构成的有序数组 |
in1d(x, y) | 返回由判断x 的元素是否在y中得到的布尔值构成的数组 |
setdiff1d(x, y) | 计算x和y的差集,返回这些元素构成的数组 |
setxor1d(x, y) | 计算x和y的对称差,返回这些元素构成的数组 |
表3:NumPy其他常用函数
| 函数 | 说明 |
|---|---|
unique | 去除数组重复元素,返回唯一元素构成的有序数组 |
copy | 返回拷贝数组得到的数组 |
sort | 返回数组元素排序后的拷贝 |
split / hsplit / vsplit | 将数组拆成若干个子数组 |
stack / hstack / vstack | 将多个数组堆叠成新数组 |
concatenate | 沿着指定的轴连接多个数组构成新数组 |
append / insert | 向数组末尾追加元素 / 在数组指定位置插入元素 |
argwhere | 找出数组中非0元素的位置 |
extract / select / where | 按照指定的条件从数组中抽取或处理数组元素 |
flip | 沿指定的轴翻转数组中的元素 |
fromiter | 通过迭代器创建数组对象 |
fromregex | 通过读取文件和正则表达式解析获取数据创建数组对象 |
repeat / tile | 通过对元素的重复来创建新数组 |
roll | 沿指定轴对数组元素进行移位 |
resize | 重新调整数组的大小 |
place / put | 将数组中满足条件的元素/指定的元素替换为指定的值 |
partition | 用选定的元素对数组进行一次划分并返回划分后的数组 |
提示:上面的
resize函数和ndarray对象的resize方法是有区别的,resize函数在调整数组大小时会重复数组中的元素作为填补多出来的元素的值,而ndarry对象的resize方法是用0来填补多出来的元素。这些小细节不清楚暂时也不要紧,但是如果用到对应的功能了就要引起注意。
矩阵运算
1 | .matrix() .mat |
线性代数模块
| 函数 | 说明 |
|---|---|
diag | 以一维数组的形式返回方阵的对角线元素或将一维数组转换为方阵(非对角元素元素为0) |
vdot | 向量的点积 |
dot | 数组的点积 |
inner | 数组的内积 |
outer | 数组的叉积 |
trace | 计算对角线元素的和 |
norm | 求模(范数)运算 |
det | 计算行列式的值(在方阵上计算会得到一个标量) |
matrix_rank | 计算矩阵的秩 |
eig | 计算矩阵的特征值(eigenvalue)和特征向量(eigenvector) |
inv | 计算非奇异矩阵(\(n\)阶方阵)的逆矩阵 |
pinv | 计算矩阵的摩尔-彭若斯(Moore-Penrose)广义逆 |
qr | QR分解(把矩阵分解成一个正交矩阵与一个上三角矩阵的积) |
svd | 计算奇异值分解(singular value decomposition) |
solve | 解线性方程组\(\boldsymbol{A}\boldsymbol{x}=\boldsymbol{b}\),其中\(\boldsymbol{A}\)是一个方阵 |
lstsq | 计算\(\boldsymbol{A}\boldsymbol{x}=\boldsymbol{b}\)的最小二乘解 |
Pandas的应用
Pandas是Wes McKinney在2008年开发的一个强大的分析结构化数据的工具集。Pandas以NumPy为基础(数据表示和运算),提供了用于数据处理的函数和方法,对数据分析和数据挖掘提供了很好的支持;同时Pandas还可以跟数据可视化工具Matplotlib很好的整合在一起,非常轻松愉快的实现数据的可视化展示。
Pandas核心的数据类型是Series(数据系列)、DataFrame(数据表/数据框),分别用于处理一维和二维的数据,除此之外还有一个名为Index的类型及其子类型,它为Series和DataFrame提供了索引功能。日常工作中以DataFrame使用最为广泛,因为二维的数据本质就是一个有行有列的表格(想一想Excel电子表格和关系型数据库中的二维表)。上述这些类型都提供了大量的处理数据的方法,数据分析师可以以此为基础实现对数据的各种常规处理
Series的应用
1 | # data参数表示数据,index参数表示数据的索引(标签) |
通过字典创建Series对象1
2
3# 字典中的键就是数据的索引(标签),字典中的值就是数据
ser2 = pd.Series({'一季度': 320, '二季度': 180, '三季度': 300, '四季度': 405})
ser2
Series对象的常用属性如下表所示。
| 属性 | 说明 |
|---|---|
dtype / dtypes | 返回Series对象的数据类型 |
hasnans | 判断Series对象中有没有空值 |
at / iat | 通过索引访问Series对象中的单个值 |
loc / iloc | 通过一组索引访问Series对象中的一组值 |
index | 返回Series对象的索引 |
is_monotonic | 判断Series对象中的数据是否单调 |
is_monotonic_increasing | 判断Series对象中的数据是否单调递增 |
is_monotonic_decreasing | 判断Series对象中的数据是否单调递减 |
is_unique | 判断Series对象中的数据是否独一无二 |
size | 返回Series对象中元素的个数 |
values | 以ndarray的方式返回Series对象中的值 |
Series对象还有一个名为describe()的方法,可以获得上述所有的描述性统计信息,如下所示。
代码:1
ser2.describe()
提示:因为
describe()返回的也是一个Series对象,所以也可以用ser2.describe()['mean']来获取平均值。
Series对象的apply()和map()方法非常重要,它们可以用于数据处理,把数据映射或转换成我们期望的样子,这个操作在数据分析的数据准备阶段非常重要。
DataFrame的应用
关于DataFrame的方法,首先需要了解的是info()方法,它可以帮助我们了解DataFrame的相关信息,如下所示。
代码:1
emp_df.info()
数据清洗
通常,我们从 Excel、CSV 或数据库中获取到的数据并不是非常完美的,里面可能因为系统或人为的原因混入了重复值或异常值,也可能在某些字段上存在缺失值;再者,DataFrame中的数据也可能存在格式不统一、量纲不统一等各种问题。因此,在开始数据分析之前,对数据进行清洗就显得特别重要。
缺失值
可以使用DataFrame对象的isnull或isna方法来找出数据表中的缺失值,如下所示。1
emp_df.isnull()
或者1
emp_df.isna()
异常值
异常值在统计学上的全称是疑似异常值,也称作离群点(outlier),异常值的分析也称作离群点分析。异常值是指样本中出现的“极端值”,数据值看起来异常大或异常小,其分布明显偏离其余的观测值。实际工作中,有些异常值可能是由系统或人为原因造成的,但有些异常值却不是,它们能够重复且稳定的出现,属于正常的极端值,例如很多游戏产品中头部玩家的数据往往都是离群的极端值。所以,我们既不能忽视异常值的存在,也不能简单地把异常值从数据分析中剔除。重视异常值的出现,分析其产生的原因,常常成为发现问题进而改进决策的契机。
异常值的检测有Z-score 方法、IQR 方法、DBScan 聚类、孤立森林等,这里我们对前两种方法做一个简单的介绍。
如果数据服从正态分布,依据3σ法则,异常值被定义与平均值的偏差超过三倍标准差的值。在正态分布下,距离平均值3σ之外的值出现的概率为$ P(|x-|>3)<0.003 $,属于小概率事件。如果数据不服从正态分布,那么可以用远离平均值的多少倍的标准差来描述,这里的倍数就是Z-score。Z-score以标准差为单位去度量某一原始分数偏离平均值的距离,公式如下所示。 \[ z = \frac {X - \mu} {\sigma} \] Z-score需要根据经验和实际情况来决定,通常把远离标准差3倍距离以上的数据点视为离群点,下面的代给出了如何通过Z-score方法检测异常值。
数据可视化
绘制图表
Series对象有一个名为plot的方法可以用来生成图表,如果选择生成折线图、饼图、柱状图等,默认会使用Series对象的索引作为横坐标,使用Series对象的数据作为纵坐标。
首先导入matplotlib中pyplot模块并进行必要的配置。1
2
3
4
5
6import matplotlib.pyplot as plt
# 配置支持中文的非衬线字体(默认的字体无法显示中文)
plt.rcParams['font.sans-serif'] = ['SimHei', ]
# 使用指定的中文字体时需要下面的配置来避免负号无法显示
plt.rcParams['axes.unicode_minus'] = False
创建Series对象并绘制对应的柱状图。1
2
3
4
5
6
7
8
9
10ser9 = pd.Series({'一季度': 400, '二季度': 520, '三季度': 180, '四季度': 380})
# 通过Series对象的plot方法绘图(kind='bar'表示绘制柱状图)
ser9.plot(kind='bar', color=['r', 'g', 'b', 'y'])
# x轴的坐标旋转到0度(中文水平显示)
plt.xticks(rotation=0)
# 在柱状图的柱子上绘制数字
for i in range(4):
plt.text(i, ser9[i] + 5, ser9[i], ha='center')
# 显示图像
plt.show()
绘图的流程
创建画布
pyplot模块的figure函数可以用来创建画布,创建画布时,可以通过figsize参数指定画布的尺寸(默认值是[6.4, 4.8]);可以通过dpi参数设置绘图的分辨率,因为dpi代表了每英寸的像素点数量。除此之外,还可以通过facecolor参数设置画布的背景色。figure函数的返回值是一个Figure对象,它代表了绘图使用的画布,我们可以基于画布来创建绘图使用的坐标系。1
plt.figure(figsize=(8, 4), dpi=120, facecolor='darkgray')
创建坐标系
可以直接使用pyplot模块的subplot函数来创建坐标系,该函数会返回Axes对象。subplot的前三个参数分别用来指定整个画布分成几行几列以及当前坐标系的索引,这三个参数的默认值都是1。如果需要在画布上创建多个坐标系,就需要使用该函数,否则就直接使用默认的也是唯一的坐标系。当然,也可以通过上面创建的Figure对象的add_subplot方法或add_axes方法来创建坐标系,前者跟subplot函数的作用一致,后者会产生嵌套的坐标系。1
plt.subplot(2, 2, 1)
绘制图像
直接查官方文档:Tutorials — Matplotlib 3.7.2 documentation
显示或保存图像
可以使用pyplot模块的show函数来显示绘制的图表,我们在上面的代码中使用过这个函数。如果希望保存图表,可以使用savefig函数。需要注意的是,如果要同时显示和保存图表,应该先执行savefig函数,再执行show函数,因为在调用show函数时,图表已经被释放,位于show函数之后的savefig保存的只是一个空白的区域。1
2plt.savefig('chart.png')
plt.show()
数据可视化-2
通过前面的学习,我们已经对数据可视化工具 matplotlib 有一个初步的认知。大家可能也会发现了,matplotlib 提供的函数虽然强大,但是参数太多,要想对图表进行深度的定制就需要修改一系列的参数,这一点对新手并不友好。另一方面,使用 matplotlib 定制的统计图是静态图表,可能在某些需要交互效果的场景下并不合适。为了解决这两个问题,我们为大家介绍两个新的可视化工具,一个是 seaborn,一个是 pyecharts。
Python-100-Days/Day66-80/76.数据可视化-2.md at master · jackfrued/Python-100-Days (github.com)
References
- https://github.com/jackfrued/Python-100-Days/blob/master/Day66-80/66.%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%A6%82%E8%BF%B0.md
