机器学习科学计算库-学习笔记整理
机器学习机器学习机器学习是从数据中自动分析获得模型,并利用模型对未知数据进行预测。机器学习工作流程机器学习工作流程总结获取数据数据基本处理特征工程机器学习(模型训练)模型评估数据集数据简介在数据集中一般:一行数据我们称为一个样本一列数据我们成为一个特征有些数据有目标值(标签值),有些数据没有目标值数据类型构成:数据类型一:特征值+目标值(目标值是连续的和离散的)数据类型二:只有特征值,没有目标值数
机器学习
机器学习
机器学习是从数据中自动分析获得模型,并利用模型对未知数据进行预测。
机器学习工作流程
机器学习工作流程总结
- 获取数据
- 数据基本处理
- 特征工程
- 机器学习(模型训练)
- 模型评估
数据集
数据简介
在数据集中一般:
- 一行数据我们称为一个样本
- 一列数据我们成为一个特征
- 有些数据有目标值(标签值),有些数据没有目标值
数据类型构成:
- 数据类型一:特征值+目标值(目标值是连续的和离散的)
- 数据类型二:只有特征值,没有目标值
数据分割:
机器学习一般的数据集会划分为两个部分:
- 训练数据:用于训练,构建模型
- 测试数据:在模型检验时使用,用于评估模型是否有效
- 划分比例:
训练集:70% 80% 75%
测试集:30% 20% 25%
数据基本处理
即对数据进行缺失值、去除异常值等处理
特征工程
特征工程是使用专业背景知识和技巧处理数据,使得特征能在机器学习算法上发挥更好的作用的过程。
意义:会直接影响机器学习的效果
特征工程包含内容
- 特征提取
- 特征预处理
- 特征降维
特征提取
特征提取:将任意数据(如文本或图像)转换为可用于机器学习的数字特征
特征预处理
特征预处理:通过一些转换函数将特征数据转换成更加适合算法模型的特征数据过程
特征降维
特征降维:指在某些限定条件下,降低随机变量(特征)个数,得到一组“不相关”主变量的过程
机器学习
选择合适的算法对模型进行训练
模型评估
对训练好的模型进行评估
机器学习算法分类
根据数据集组成不同,可以把机器学习算法分为:
- 监督学习
输入数据是由输入特征值和目标值所组成- 回归问题 – 目标值是连续
- 分类问题 – 目标值是离散的
- 无监督学习
输入数据是由输入特征值组成 - 半监督学习
有特征值,但是一部分数据有目标值,其他数据没有目标值 - 强化学习
实质是,自动进行决策,并且可以做连续决策
主要包含四个元素:agent,环境状态(environment),行动(action),奖励(reward);
模型评估
按照数据集的目标值不同,可以把模型评估分为分类模型评估和回归模型评估。
分类模型评估
- 准确率
预测正确的数占样本总数的比例。 - 精确率
正确预测为正占全部预测为正的比例 - 召回率
正确预测为正占全部正样本的比例 - F1-score
主要用于评估模型的稳健性 - AUC指标
主要用于评估样本不均衡的情况
回归模型评估
- 均方根误差(Root Mean Squared Error,RMSE)
RMSE是一个衡量回归模型误差率的常用公式。 然而,它仅能比较误差是相同单位的模型。
- 相对平方误差(Relative Squared Error,RSE)
与RMSE不同,RSE可以比较误差是不同单位的模型。
- 平均绝对误差(Mean Absolute Error,MAE)
MAE与原始数据单位相同, 它仅能比较误差是相同单位的模型。量级近似与RMSE,但是误差值相对小一些。
- 相对绝对误差(Relative Absolute Error,RAE)
与RSE不同,RAE可以比较误差是不同单位的模型。
- 决定系数 (Coefficient of Determination)
决定系数 ( R2)回归模型汇总了回归模型的解释度,由平方和术语计算而得。
R2描述了回归模型所解释的因变量方差在总方差中的比例。R2很大,即自变量和因变量之间存在线性关系,如果回归模型是“完美的”,SSE为零,则R2为1。R2小,则自变量和因变量之间存在线性关系的证据不令人信服。如果回归模型完全失败,SSE等于SST,没有方差可被回归解释,则R2为零。
SSE和SSR关系
拟合
模型评估用于评价训练好的的模型的表现效果,其表现效果大致可以分为两类:过拟合、欠拟合。
- 欠拟合
- 学习到的东西太少
- 学习到的特征少
- 过拟合
- 学习到的东西太多
- 学习到的特征多,不好泛化
机器学习基础环境安装与使用
requirements.txt
matplotlib==2.2.2
numpy==1.14.2
pandas==0.20.3
tables==3.4.2
jupyter==1.0.0
pip3 install -r requirements.txt
Jupyter
Jupyter支持两种模式:
- 编辑模式(Enter)
- 命令模式下回车Enter或鼠标双击cell进入编辑模式
- 可以操作cell内文本或代码,剪切/复制/粘贴移动等操作
- 命令模式(Esc)
- 按Esc退出编辑,进入命令模式
- 可以操作cell单元本身进行剪切/复制/粘贴/移动等操作
快捷键操作
两种模式通用快捷键
-
Shift+Enter,执行本单元代码,并跳转到下一单元
-
Ctrl+Enter,执行本单元代码,留在本单元
cell行号前的 * ,表示代码正在运行,cell:一对In Out会话被视作一个代码单元,称为cell -
命令模式:按ESC进入
- Y,cell切换到Code模式
- M,cell切换到Markdown模式
- A,在当前cell的上面添加cell
- B,在当前cell的下面添加cell
- 双击D:删除当前cell
- Z,回退
- L,为当前cell加上行号 <!–
- Ctrl+Shift+P,对话框输入命令直接运行
- 快速跳转到首个cell,Crtl+Home
- 快速跳转到最后一个cell,Crtl+End -->
-
编辑模式:按Enter进入
- 多光标操作:Ctrl键点击鼠标(Mac:CMD+点击鼠标)
- 回退:Ctrl+Z(Mac:CMD+Z)
- 重做:Ctrl+Y(Mac:CMD+Y)
- 补全代码:变量、方法后跟Tab键
- 为一行或多行代码添加/取消注释:Ctrl+/(Mac:CMD+/)
- 屏蔽自动输出信息:可在最后一条语句之后加一个分号
Matplotlib
是专门用于开发2D图表(包括3D图表)
使用起来及其简单
以渐进、交互式方式实现数据可视化
可视化是在整个数据挖掘的关键辅助工具,可以清晰的理解数据,从而调整我们的分析方法。
- 能将数据进行可视化,更直观的呈现
- 使数据更加客观、更具说服力
import matplotlib.pyplot as plt
# 1.创建画布
plt.figure(figsize=(20,8), dpi=100)
# 2.绘制图像
x = [1,2,3]
y = [4,5,6]
plt.plot(x, y)
# 3.显示图像
plt.show()
Matplotlib 图像结构
Matplotlib三层结构
容器层
容器层主要由Canvas、Figure、Axes组成。
Canvas是位于最底层的系统层,在绘图的过程中充当画板的角色,即放置画布(Figure)的工具。
Figure是Canvas上方的第一层,也是需要用户来操作的应用层的第一层,在绘图的过程中充当画布的角色。
Axes是应用层的第二层,在绘图的过程中相当于画布上的绘图区的角色。
- Figure:指整个图形(可以通过plt.figure()设置画布的大小和分辨率等)
- Axes(坐标系):数据的绘图区域
- Axis(坐标轴):坐标系中的一条轴,包含大小限制、刻度和刻度标签
特点为:
- 一个figure(图像)可以包含多个axes(坐标系/绘图区),但是一个axes只能属于一个figure。
- 一个axes(坐标系/绘图区)可以包含多个axis(坐标轴),包含两个即为2d坐标系,3个即为3d坐标系
辅助显示层
辅助显示层为Axes(绘图区)内的除了根据数据绘制出的图像以外的内容,主要包括Axes外观(facecolor)、边框线(spines)、坐标轴(axis)、坐标轴名称(axis label)、坐标轴刻度(tick)、坐标轴刻度标签(tick label)、网格线(grid)、图例(legend)、标题(title)等内容。
该层的设置可使图像显示更加直观更加容易被用户理解,但又不会对图像产生实质的影响。
图像层
图像层指Axes内通过plot、scatter、bar、histogram、pie等函数根据数据绘制出的图像。
总结:
- Canvas(画板)位于最底层,用户一般接触不到
- Figure(画布)建立在Canvas之上
- Axes(绘图区)建立在Figure之上
- 坐标轴(axis)、图例(legend)等辅助显示层以及图像层都是建立在Axes之上
折线图(plot)与基础绘图功能
matplotlib.pyplot模块
matplotlib.pytplot包含了一系列类似于matlab的画图函数。 它的函数作用于当前图形(figure)的当前坐标系(axes)。
import matplotlib.pyplot as plt
折线图绘制与显示
展现一周的天气,比如从星期一到星期日的天气温度如下
# 1.创建画布(容器层)
plt.figure(figsize=(10, 10))
# 2.绘制折线图(图像层)
plt.plot([1, 2, 3, 4, 5, 6 ,7], [17,17,18,15,11,11,13])
# 3.显示图像
plt.show()
设置画布属性与图片保存
plt.figure(figsize=(), dpi=)
figsize:指定图的长宽
dpi:图像的清晰度
返回fig对象
plt.savefig(path)
# 1.创建画布,并设置画布属性
plt.figure(figsize=(20, 8), dpi=80)
# 2.保存图片到指定路径
plt.savefig("test.png")
注意:plt.show()会释放figure资源,如果在显示图像之后保存图片将只能保存空图片
准备数据并画出初始折线图
# 画出温度变化图
# 0.准备x, y坐标的数据
x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x]
# 1.创建画布
plt.figure(figsize=(20, 8), dpi=80)
# 2.绘制折线图
plt.plot(x, y_shanghai)
# 3.显示图像
plt.show()
添加自定义x,y刻度
plt.xticks(x, **kwargs)
x:要显示的刻度值
plt.yticks(y, **kwargs)
y:要显示的刻度值
# 增加以下两行代码
# 构造x轴刻度标签
x_ticks_label = ["11点{}分".format(i) for i in x]
# 构造y轴刻度
y_ticks = range(40)
# 修改x,y轴坐标的刻度显示
plt.xticks(x[::5], x_ticks_label[::5])
plt.yticks(y_ticks[::5])
jupyter notebook中文显示问题解决
下载中文字体(黑体,看准系统版本)
下载 SimHei 字体(或者其他的支持中文显示的字体也行)
安装字体
linux下:拷贝字体到 usr/share/fonts 下:
sudo cp ~/SimHei.ttf /usr/share/fonts/SimHei.ttf
windows和mac下:双击安装
删除~/.matplotlib中的缓存文件
cd ~/.matplotlib
rm -r *
修改配置文件matplotlibrc
vi ~/.matplotlib/matplotlibrc
将文件内容修改为:
font.family : sans-serif
font.sans-serif : SimHei
axes.unicode_minus : False
添加网格显示
为了更加清楚地观察图形对应的值
plt.grid(True, linestyle='--', alpha=0.5)
添加描述信息
添加x轴、y轴描述信息及标题
plt.xlabel("时间")
plt.ylabel("温度")
plt.title("中午11点0分到12点之间的温度变化图示")
需求:再添加一个城市的温度变化
# 增加北京的温度数据
y_beijing = [random.uniform(1, 3) for i in x]
# 绘制折线图
plt.plot(x, y_shanghai, label="上海")
# 使用多次plot可以画多个折线
plt.plot(x, y_beijing, color='r', linestyle='--', label="北京")
# 显示图例
plt.legend(loc="best")
设置图形风格
显示图例
注意:如果只在plt.plot()中设置label还不能最终显示出图例,还需要通过plt.legend()将图例显示出来。
plt.legend(loc="best")
完整代码:
import matplotlib.pyplot as plt
import random
# 多次plot
# 0.创建数据
x = range(60)
y_shanghai = [random.uniform(15,18) for i in x]
y_beijing = [random.uniform(-5, 5) for i in x]
# 1.创建画布
plt.figure(figsize=(20, 8), dpi=100)
# 2.绘制图
plt.plot(x, y_shanghai, label="上海", color="r", linestyle="--")
plt.plot(x, y_beijing, label="北京")
# 2.1 添加x,y轴的刻度
x_labels_ticks = ["11点{}分".format(i) for i in x]
y_labels_ticks = range(-10, 30)
plt.xticks(x[::5], x_labels_ticks[::5])
plt.yticks(y_labels_ticks[::5])
# 2.2 添加网格线
plt.grid(linestyle="--", alpha=0.5)
# 2.3 添加描述信息
plt.xlabel("时间", fontsize=16)
plt.ylabel("温度", fontsize=16)
plt.title("某城市11点-12点温度变化", fontsize=20)
# 2.4 增加图例
plt.legend(loc="best")
# 3.显示
plt.show()
多个坐标系显示-plt.subplots(面向对象的画图方法)
可以通过subplots函数实现(旧的版本中有subplot,使用起来不方便),推荐subplots函数
matplotlib.pyplot.subplots(nrows=1, ncols=1, **fig_kw) 创建一个带有多个axes(坐标系/绘图区)的图
Parameters:
nrows, ncols : int, optional, default: 1, Number of rows/columns of the subplot grid.
**fig_kw : All additional keyword arguments are passed to the figure() call.
Returns:
fig : 图对象
ax :
设置标题等方法不同:
set_xticks
set_yticks
set_xlabel
set_ylabel
注意:plt.函数名()相当于面向过程的画图方法,axes.set_方法名()相当于面向对象的画图方法。
# 需求:画出某城市11点到12点1小时内每分钟的温度变化折线图,温度范围在15度~18度
# 多个axes
# 0.构造数据
x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x]
y_beijing = [random.uniform(1, 14) for i in x]
# 1.创建画布
# plt.figure(figsize=(20, 8))
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 8), dpi=100)
# 2.图像绘制
# plt.plot(x, y_shanghai, label="上海")
# plt.plot(x, y_beijing, label="北京", linestyle="--", color="r")
axes[0].plot(x, y_shanghai, label="上海")
axes[1].plot(x, y_beijing, label="北京", linestyle="--", color="r")
# 2.1 添加x,y轴刻度
x_ticks_label = ["11点{}分".format(i) for i in x]
y_ticks = range(40)
# plt.xticks(x[::5], x_ticks_label[::5])
# plt.yticks(y_ticks[::5])
axes[0].set_xticks(x[::5])
axes[0].set_yticks(y_ticks[::5])
axes[0].set_xticklabels(x_ticks_label[::5])
axes[1].set_xticks(x[::5])
axes[1].set_yticks(y_ticks[::5])
axes[1].set_xticklabels(x_ticks_label[::5])
# 2.2 添加网格显示
# plt.grid(True, linestyle="--", alpha=0.5)
axes[0].grid(True, linestyle="--", alpha=0.5)
axes[1].grid(True, linestyle="--", alpha=0.5)
# 2.3 添加x,y轴描述和标题
# plt.xlabel("时间")
# plt.ylabel("温度")
# plt.title("中午11点--12点温度变化图", fontsize=25)
axes[0].set_xlabel("时间")
axes[0].set_ylabel("温度")
axes[0].set_title("上海中午11点--12点温度变化图", fontsize=25)
axes[1].set_xlabel("时间")
axes[1].set_ylabel("温度")
axes[1].set_title("北京中午11点--12点温度变化图", fontsize=25)
# 2.4 显示图例
# plt.legend(loc=0)
axes[0].legend(loc=0)
axes[1].legend(loc=0)
# 3.显示
plt.show()
画各种数学函数图像
import matplotlib.pyplot as plt
import numpy as np
# 0.准备数据
x = np.linspace(-10, 10, 1000)
y = np.sin(x)
# 1.创建画布
plt.figure(figsize=(20, 8), dpi=100)
# 2.绘制函数图像
plt.plot(x, y)
# 2.1 添加网格显示
plt.grid()
# 3.显示图像
plt.show()
常见图形绘制
-
折线图:以折线的上升或下降来表示统计数量的增减变化的统计图
特点:能够显示数据的变化趋势,反映事物的变化情况。(变化)
api:plt.plot(x, y)
- 散点图:用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或总结坐标点的分布模式。
特点:判断变量之间是否存在数量关联趋势,展示离群点(分布规律)
api:plt.scatter(x, y)
- 柱状图:排列在工作表的列或行中的数据可以绘制到柱状图中。
特点:绘制连离散的数据,能够一眼看出各个数据的大小,比较数据之间的差别。(统计/对比)
api:plt.bar(x,y, width, align='center', **kwargs)
import matplotlib.pyplot as plt # 创建画布 plt.figure(figsize=(20,8)) # 绘制图形 movie_names = ["雷神","正义联盟","诸神黄昏","77天"] y = [553,884,323,565] # 先构建X轴 x = range(len(movie_names)) # 设置X的刻度 plt.xticks(x,movie_names) plt.bar(x,y,width=0.5,color=['r','y','b','g']) # 显示图形 plt.show()
- 直方图:由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据范围,纵轴表示分布情况。
特点:绘制连续性的数据展示一组或者多组数据的分布状况(统计)
api:matplotlib.pyplot.hist(x, bins=None)
import matplotlib.pyplot as plt import random # 均匀分布 x = np.random.uniform(-10,10,10000000) # 创建画布 plt.figure(figsize=(20,8),dpi=100) # 绘制直方图 plt.hist(x,bins=1000) # bins 为分成的区间个数 # 显示图像 plt.show()
- 饼图:用于表示不同分类的占比情况,通过弧度大小来对比各种分类。
特点:分类数据的占比情况(占比)
api:plt.pie(x, labels=,autopct=,colors)
x:数量,自动算百分比 labels:每部分名称 autopct:占比显示指定%1.2f%% colors:每部分颜色
- 散点图:用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或总结坐标点的分布模式。
numpy
Numpy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。
Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。
Numpy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器。
ndarray介绍
NumPy provides an N-dimensional array type, the ndarray, which describes a collection of “items” of the same type.
NumPy提供了一个N维数组类型ndarray,它描述了相同类型的“items”的集合
用ndarray进行存储:
import numpy as np
# 创建ndarray
score = np.array([[80, 89, 86, 67, 79],
[78, 97, 89, 67, 81],
[90, 94, 78, 67, 74],
[91, 91, 90, 67, 69],
[76, 87, 75, 67, 86],
[70, 79, 84, 67, 84],
[94, 92, 93, 67, 64],
[86, 85, 83, 67, 80]])
score
返回结果:
array([[80, 89, 86, 67, 79],
[78, 97, 89, 67, 81],
[90, 94, 78, 67, 74],
[91, 91, 90, 67, 69],
[76, 87, 75, 67, 86],
[70, 79, 84, 67, 84],
[94, 92, 93, 67, 64],
[86, 85, 83, 67, 80]])
ndarray与Python原生list运算效率对比
import random
import time
import numpy as np
a = []
for i in range(100000000):
a.append(random.random())
# 通过%time魔法方法, 查看当前行的代码运行一次所花费的时间
%time sum1=sum(a)
b=np.array(a)
%time sum2=np.sum(b)
可以看出ndarray的计算速度要快很多,节约了时间。
机器学习的最大特点就是大量的数据运算,那么如果没有一个快速的解决方案,那可能现在python也在机器学习领域达不到好的效果。
Numpy专门针对ndarray的操作和运算进行了设计,所以数组的存储效率和输入输出性能远优于Python中的嵌套列表,数组越大,Numpy的优势就越明显。
ndarray的优势
内存块风格
ndarray在存储数据的时候,数据与数据的地址都是连续的,这样就给使得批量操作数组元素时速度更快。
这是因为ndarray中的所有元素的类型都是相同的,而Python列表中的元素类型是任意的,所以ndarray在存储元素时内存可以连续,而python原生list就只能通过寻址方式找到下一个元素,这虽然也导致了在通用性能方面Numpy的ndarray不及Python原生list,但在科学计算中,Numpy的ndarray就可以省掉很多循环语句,代码使用方面比Python原生list简单的多。
ndarray支持并行化运算(向量化运算)
效率远高于纯Python代码
Numpy底层使用C语言编写,内部解除了GIL(全局解释器锁),其对数组的操作速度不受Python解释器的限制,所以,其效率远高于纯Python代码。
ndarray的属性
数组属性反映了数组本身固有的信息。
ndarray.shape 数组维度的元组
ndarray.ndim 数组维数
ndarray.size 数组中的元素数量
ndarray.itemsize 一个数组元素的长度(字节)
ndarray.dtype 数组元素的类型
ndarray的形状
# 创建不同形状的数组
>>> a = np.array([[1,2,3],[4,5,6]])
>>> b = np.array([1,2,3,4])
>>> c = np.array([[[1,2,3],[4,5,6]],[[1,2,3],[4,5,6]]])
>>> a.shape
>>> b.shape
>>> c.shape
(2, 3) # 二维数组
(4,) # 一维数组
(2, 2, 3) # 三维数组
ndarray的类型
>>> type(score.dtype)
<type 'numpy.dtype'>
dtype是numpy.dtype类型,先看看对于数组来说都有哪些类型
创建数组的时候指定类型
>>> a = np.array([[1, 2, 3],[4, 5, 6]], dtype=np.float32)
>>> a.dtype
dtype('float32')
>>> arr = np.array(['python', 'tensorflow', 'scikit-learn', 'numpy'], dtype = np.string_)
>>> arr
array([b'python', b'tensorflow', b'scikit-learn', b'numpy'], dtype='|S12')
注意:若不指定,整数默认int64,小数默认float64
生成数组的方法
生成0和1的数组
- np.ones(shape[, dtype, order])
- np.ones_like(a[, dtype, order, subok])
- np.zeros(shape[, dtype, order])
- np.zeros_like(a[, dtype, order, subok])
>>> zero = np.zeros([3, 4])
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
从现有数组生成
生成方式
- np.array(object[, dtype, copy, order, subok, ndmin])
- np.asarray(a[, dtype, order])
a = np.array([[1,2,3],[4,5,6]])
# 从现有的数组当中创建
a1 = np.array(a)
# 相当于索引的形式,并没有真正的创建一个新的
a2 = np.asarray(a)
关于array和asarray的不同
生成固定范围的数组
np.linspace (start, stop, num, endpoint)
生成等间隔的序列
start 序列的起始值
stop 序列的终止值,
num 要生成的等间隔样例数量,默认为50
endpoint 序列中是否包含stop值,默认为ture
# 生成等间隔的数组
np.linspace(0, 100, 11)
# 返回结果
array([ 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.])
其它的还有
numpy.arange(start,stop, step, dtype)
numpy.logspace(start,stop, num)
np.arange(10, 50, 2)
返回结果:
array([10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42,
44, 46, 48])
# 生成10^x
np.logspace(0, 2, 3)
返回结果:
array([ 1., 10., 100.])
生成随机数组
使用模块介绍
np.random模块
均匀分布
np.random.rand(d0, d1, ..., dn)
返回[0.0,1.0)内的一组均匀分布的数。
np.random.uniform(low=0.0, high=1.0, size=None)
功能:从一个均匀分布[low,high)中随机采样,注意定义域是左闭右开,即包含low,不包含high.
参数介绍:
low: 采样下界,float类型,默认值为0;
high: 采样上界,float类型,默认值为1;
size: 输出样本数目,为int或元组(tuple)类型,例如,size=(m,n,k), 则输出mnk个样本,缺省时输出1个值。
返回值:ndarray类型,其形状和参数size中描述一致。
np.random.randint(low, high=None, size=None, dtype='l')
从一个均匀分布中随机采样,生成一个整数或N维整数数组,取数范围:若high不为None时,取[low,high)之间随机整数,否则取值[0,low)之间随机整数。
# 生成均匀分布的随机数
x1 = np.random.uniform(-1, 1, 100000000)
返回结果:
array([ 0.22411206, 0.31414671, 0.85655613, ..., -0.92972446,
0.95985223, 0.23197723])
画图看分布状况:
import matplotlib.pyplot as plt
# 生成均匀分布的随机数
x1 = np.random.uniform(-1, 1, 100000000)
# 画图看分布状况
# 1)创建画布
plt.figure(figsize=(10, 10), dpi=100)
# 2)绘制直方图
plt.hist(x=x1, bins=1000) # x代表要使用的数据,bins表示要划分区间数
# 3)显示图像
plt.show()
正态分布
正态分布是一种概率分布。正态分布是具有两个参数μ和σ的连续型随机变量的分布,第一参数μ是服从正态分布的随机变量的均值,第二个参数σ是此随机变量的方差,所以正态分布记作N(μ,σ )。
正态分布特点
μ决定了其位置,其标准差σ决定了分布的幅度。当μ = 0,σ = 1时的正态分布是标准正态分布。
方差
是在概率论和统计方差衡量一组数据时离散程度的度量
其中M为平均值,n为数据总个数,S为标准差,S2可以理解一个整体为方差
正态分布创建方式
np.random.randn(d0, d1, …, dn)
功能:从标准正态分布中返回一个或多个样本值
np.random.normal(loc=0.0, scale=1.0, size=None)
loc:float
此概率分布的均值(对应着整个分布的中心centre)
scale:float
此概率分布的标准差(对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高)
size:int or tuple of ints
输出的shape,默认为None,只输出一个值
np.random.standard_normal(size=None)
返回指定形状的标准正态分布的数组。
x2 = np.random.normal(1.75, 1, 100000000)
返回结果:
array([2.90646763, 1.46737886, 2.21799024, ..., 1.56047411, 1.87969135,
0.9028096 ])
import matplotlib.pyplot as plt
import random
# 生成均匀分布的随机数
x2 = np.random.normal(1.75, 1, 100000000)
# 画图看分布状况
# 1)创建画布
plt.figure(figsize=(20, 10), dpi=100)
# 2)绘制直方图
plt.hist(x2, 1000)
# 3)显示图像
plt.show()
数组的索引、切片
案例:随机生成8只股票2周的交易日涨幅数据
import random
# 随机生成8行10列的数组
stock_change = np.random.standard_normal((8,10))
stock_change
array([[ 0.14401682, -1.48963539, -0.8895709 , -0.34989962, -0.97773321,
-0.74861063, 0.26386878, 1.27982551, 1.12473295, 0.18776722],
[ 0.27111159, -1.28547271, -0.85684537, 1.74141715, -1.73204494,
1.52240873, -0.46314502, -0.60541425, 1.00799328, 0.70257848],
[-1.43352805, 0.12857923, -0.65452426, -0.42321317, -0.48861617,
0.43218611, -0.92345367, 0.72922499, -0.6405581 , 0.12503792],
[ 0.35952641, -1.24174139, 0.75046079, 0.13072002, 0.48565156,
-0.26730213, 0.32302435, -0.72131556, -0.995412 , -1.36096473],
[-0.02209019, -0.35493271, -0.69888324, -0.38827834, 0.65855429,
-0.75036987, -0.68924239, 1.63248018, 0.3047486 , -0.51231325],
[ 1.86970181, -0.29139264, -0.90990551, -0.65727445, 0.18708323,
-0.49455804, 0.12187795, 0.78919161, 0.99579209, -0.14336594],
[ 0.18919138, -1.00346025, -0.71156217, -1.06322924, -1.90883858,
-1.14991256, -1.9027262 , -0.60638635, 0.45175841, 1.99453615],
[ 0.32861702, 0.7616844 , -2.0241717 , -0.12842078, -2.0839974 ,
-0.69092221, -1.37096095, -1.05165983, -0.82271123, 0.69256602]])
切片
-切片方法 每个维度用冒号索引进行切片[起:止:步长],多少维度就用多少冒号索引
# stock_changek[,] 切片 ,左边为行索引 右侧为列索引,
stock_change[0,0]
0.14401682
stock_change[0,0] =10
stock_change
形状修改
- ndarray.reshape(shape[, order]) Returns an array containing the same data with a new shape.
- ndarray.resize(new_shape[, refcheck]) Change shape and size of array in-place.
- ndarray.T 数组的转置
将数组的行、列进行互换
类型修改
数据去重
np.unique()
temp = np.array([[1, 2, 3, 4],[3, 4, 5, 6]])
>>> np.unique(temp)
array([1, 2, 3, 4, 5, 6])
ndarry 运算
逻辑运算
# 重新生成8只股票10个交易日的涨跌幅数据
>>> stock_change = np.random.normal(0, 1, (8, 10))
>>> stock_change = stock_change[0:5, 0:5]
# 逻辑判断, 如果涨跌幅大于0.5就标记为True 否则为False
>>> stock_change > 0.5
array([[ True, False, False, True, False],
[ True, True, False, False, False],
[ True, False, True, False, True],
[False, True, False, False, False],
[False, False, False, True, True]])
# BOOL赋值, 将满足条件的设置为指定的值-布尔索引
>>> stock_change[stock_change > 0.5] = 1
array([[ 1. , -0.72404879, -1.33045773, 1. , 0.3869043 ],
[ 1. , 1. , 0.20815446, -1.67860823, 0.06612823],
[ 1. , 0.42753488, 1. , -0.24375089, 1. ],
[-0.971945 , 1. , -0.95444661, -0.2602084 , -0.48736497],
[-0.32183056, -0.92544956, -0.42126604, 1. , 1. ]])
通用判断函数
np.all()
# 判断stock_change[0:2, 0:5]是否全是上涨的
>>> np.all(stock_change[0:2, 0:5] > 0)
False
np.any()
# 判断前5只股票这段期间是否有上涨的
>>> np.any(stock_change[0:5, :] > 0 )
True
np.where(三元运算符)
通过使用np.where能够进行更加复杂的运算
np.where()
# 判断前四个股票前四天的涨跌幅 大于0的置为1,否则为0
temp = stock_change[:4, :4]
np.where(temp > 0, 1, 0)
复合逻辑需要结合np.logical_and和np.logical_or使用
# 判断前四个股票前四天的涨跌幅 大于0.5并且小于1的,换为1,否则为0
# 判断前四个股票前四天的涨跌幅 大于0.5或者小于-0.5的,换为1,否则为0
np.where(np.logical_and(temp > 0.5, temp < 1), 1, 0)
np.where(np.logical_or(temp > 0.5, temp < -0.5), 1, 0)
统计运算
- min(a[, axis, out, keepdims])
Return the minimum of an array or minimum along an axis. - max(a[, axis, out, keepdims])
Return the maximum of an array or maximum along an axis. - median(a[, axis, out, overwrite_input, keepdims])
Compute the median along the specified axis. - mean(a[, axis, dtype, out, keepdims])
Compute the arithmetic mean along the specified axis. - std(a[, axis, dtype, out, ddof, keepdims])
Compute the standard deviation along the specified axis. - var(a[, axis, dtype, out, ddof, keepdims])
Compute the variance along the specified axis.
axis 轴的取值并不一定,Numpy中不同的API轴的值都不一样,在这里,axis 0代表列, axis 1代表行去进行统计
# 接下来对于这4只股票的4天数据,进行一些统计运算
# 指定行 去统计
print("前四只股票前四天的最大涨幅{}".format(np.max(temp, axis=1)))
# 使用min, std, mean
print("前四只股票前四天的最大跌幅{}".format(np.min(temp, axis=1)))
print("前四只股票前四天的波动程度{}".format(np.std(temp, axis=1)))
print("前四只股票前四天的平均涨跌幅{}".format(np.mean(temp, axis=1)))
统计出哪一只股票在某个交易日的涨幅最大或者最小
np.argmax(temp, axis=)
np.argmin(temp, axis=)
# 获取股票指定哪一天的涨幅最大
print("前四只股票前四天内涨幅最大{}".format(np.argmax(temp, axis=1)))
print("前四天一天内涨幅最大的股票{}".format(np.argmax(temp, axis=0)))
数组间运算
数组与数的运算
数组与数组的运算
广播机制
执行 broadcast 的前提在于,两个 ndarray 执行的是 element-wise的运算,Broadcast机制的功能是为了方便不同形状的ndarray(numpy库的核心数据结构)进行数学运算。
当操作两个数组时,numpy会逐个比较它们的shape(构成的元组tuple),只有在下述情况下,两个数组才能够进行数组与数组的运算。
- 维度相等
- shape(其中相对应的一个地方为1)
Image (3d array): 256 x 256 x 3
Scale (1d array): 3
Result (3d array): 256 x 256 x 3
A (4d array): 9 x 1 x 7 x 1
B (3d array): 8 x 1 x 5
Result (4d array): 9 x 8 x 7 x 5
A (2d array): 5 x 4
B (1d array): 1
Result (2d array): 5 x 4
A (3d array): 15 x 3 x 5
B (3d array): 15 x 1 x 1
Result (3d array): 15 x 3 x 5
如果是下面这样,则不匹配:
A (1d array): 10
B (1d array): 12
A (2d array): 2 x 1
B (3d array): 8 x 4 x 3`
矩阵乘法api
- np.matmul
- np.dot
>>> a = np.array([[80, 86],
[82, 80],
[85, 78],
[90, 90],
[86, 82],
[82, 90],
[78, 80],
[92, 94]])
>>> b = np.array([[0.7], [0.3]])
>>> np.matmul(a, b)
array([[81.8],
[81.4],
[82.9],
[90. ],
[84.8],
[84.4],
[78.6],
[92.6]])
>>> np.dot(a,b)
array([[81.8],
[81.4],
[82.9],
[90. ],
[84.8],
[84.4],
[78.6],
[92.6]])
np.matmul和np.dot的区别
二者都是矩阵乘法。 np.matmul中禁止矩阵与标量的乘法。 在矢量乘矢量的內积运算中,np.matmul与np.dot没有区别。
Pandas
- 2008年WesMcKinney开发出的库
- 专门用于数据挖掘的开源python库
- 以Numpy为基础,借力Numpy模块在计算方面性能高的优势
- 基于matplotlib,能够简便的画图
- 独特的数据结构
Pandas优势
- 便捷的数据处理能力
- 读取文件方便
- 封装了Matplotlib、Numpy的画图和计算
案例:获取两周内8支股票走势
import numpy as np
import pandas as pd
stock_change = np.random.standard_normal((8,10))
stock_change
array([[-0.05754788, 0.21029898, -0.03265957, 1.30351707, 0.33197182,
1.56983804, -0.23480505, -1.65475427, 0.46816427, -0.48388722],
[ 0.41802156, -0.27505386, -1.54310245, -0.25989823, -0.39275176,
-0.25082766, -1.10979654, -0.47782569, 0.41750598, -0.72252277],
[ 0.97766123, 0.97637506, 1.01732863, 0.2499813 , 0.06167437,
0.13933275, -1.84336271, 1.47588191, 0.14630719, 0.35324661],
[ 1.59041433, -1.08861395, 0.30696252, -0.58626648, 1.78051606,
0.07977819, -0.47066406, -1.60293909, -0.14450208, 0.21785362],
[ 0.95166164, 0.33578104, -1.25532418, -0.45929209, -0.42486285,
-0.34487713, 0.00922157, 1.18608095, 0.27595473, 0.63853717],
[-0.07249857, -1.20066942, 0.64326827, -0.13906129, -2.04712474,
-0.12335355, 0.3131091 , 1.22563968, 0.53614054, -1.62965967],
[ 0.37837798, -2.08070101, 0.58598907, -0.45026638, -0.35867323,
0.18418201, 0.18236871, -0.05144433, -1.45733102, -1.70084381],
[ 0.24184604, -0.37030245, 1.22672516, 0.72156162, -0.71482026,
-0.75437147, -0.62633426, -0.31137122, -0.56577178, 0.76745035]])
使用pandas的数据结构
data = pd.DataFrame(stock_change)
data
生成以股票名字和日期的行、列索引
codes = ['股票'+str(i) for i in range(8)]
codes
# 生成日期数据 date_range('开始日期',periods=天数,freq='B'-是否跳过周末)
date = pd.date_range('20200101',periods=10,freq='B')
date
# 设置行列名字
data = pd.DataFrame(stock_change,index=codes,columns=date)
data
DataFrame结构
DataFrame对象既有行索引,又有列索引
- 行索引,表明不同行,横向索引,叫index,0轴,axis=0
- 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
DataFrame的属性
- shape 获取DataFrame形状
- index DataFrame的行索引列表
- columns DataFrame的列索引列表
- values 直接获取其中array的值
- T 转置
- head(5):显示前5行内容 如果不补充参数,默认5行。填入参数N则显示前N行
- tail(5):显示后5行内容 如果不补充参数,默认5行。填入参数N则显示后N行
DatatFrame索引的设置
- 修改行列索引值
# 生成新的index列表
new_index = ['股票_'+str(i) for i in range(8)]
# 替换旧索引 ,必须整体全部修改
data.index = new_index
- reset_index(drop=True) 重置索引 drop为控制是否舍弃旧索引,若不指定,则默认旧索引作为数据的一部分保留
以某列值设置为新的索引
set_index(keys, drop=True)
- keys : 列索引名成或者列索引名称的列表
- drop : boolean, default True.当做新的索引,删除原来的列
df = pd.DataFrame({'month': [1, 4, 7, 10],
'year': [2012, 2014, 2013, 2014],
'sale':[55, 40, 84, 31]})
month sale year
0 1 55 2012
1 4 40 2014
2 7 84 2013
3 10 31 2014
以月份设置新的索引
df.set_index('month')
sale year
month
1 55 2012
4 40 2014
7 84 2013
10 31 2014
设置多个索引,以年和月份
df.set_index(['year', 'month'])
sale
year month
2012 1 55
2014 4 40
2013 7 84
2014 10 31
注:通过刚才的设置,这样DataFrame就变成了一个具有MultiIndex的DataFrame。
MultiIndex与Panel
打印刚才的df的行索引结果
df.index
MultiIndex(levels=[[2012, 2013, 2014], [1, 4, 7, 10]],
labels=[[0, 2, 1, 2], [0, 1, 2, 3]],
names=['year', 'month'])
MultiIndex
多级或分层索引对象。
- index属性
- names:levels的名称
- levels:每个level的元组值
df.index.names
FrozenList(['year', 'month'])
df.index.levels
FrozenList([[1, 2], [1, 4, 7, 10]])
Panel
- class pandas.Panel(data=None, items=None, major_axis=None, minor_axis=None, copy=False, dtype=None)
- 存储3维数组的Panel结构
p = pd.Panel(np.arange(24).reshape(4,3,2),
items=list('ABCD'),
major_axis=pd.date_range('20130101', periods=3),
minor_axis=['first', 'second'])
p
<class 'pandas.core.panel.Panel'>
Dimensions: 4 (items) x 3 (major_axis) x 2 (minor_axis)
Items axis: A to D
Major_axis axis: 2013-01-01 00:00:00 to 2013-01-03 00:00:00
Minor_axis axis: first to second
- items - axis 0,每个项目对应于内部包含的数据帧(DataFrame)。
- major_axis - axis 1,它是每个数据帧(DataFrame)的索引(行)。
- minor_axis - axis 2,它是每个数据帧(DataFrame)的列。
查看panel数据:
p[:,:,"first"]
p["B",:,:]
注:Pandas从版本0.20.0开始弃用:推荐的用于表示3D数据的方法是通过DataFrame上的MultiIndex方法
Series结构
series结构只有行索引
创建series
通过已有数据创建
- 指定内容,默认索引
pd.Series(np.arange(10))
- 指定索引
pd.Series([6.7,5.6,3,10,2], index=[1,2,3,4,5])
- 通过字典数据创建
pd.Series({'red':100, ''blue':200, 'green': 500, 'yellow':1000})
基本数据操作
索引操作
# 读取文件
data = pd.read_csv("./data/stock_day.csv")
# 删除一些列
data = data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"], axis=1)
# 通过[]索引
data['close'].head() # Series
data['close']['2018-02-22'] # 先列后行
# loc索引 通过索引名字,先行后列
data.loc['2018-02-23','close':'low'] # Series
# iloc 通过索引下标
data.iloc[2,2:4]
获取行第1天到第4天,['open', 'close', 'high', 'low']这个四个指标的结果
# 使用ix进行下表和名称组合做引
data.ix[0:4, ['open', 'close', 'high', 'low']]
# 推荐使用loc和iloc来获取的方式
data.loc[data.index[0:4], ['open', 'close', 'high', 'low']]
data.iloc[0:4, data.columns.get_indexer(['open', 'close', 'high', 'low'])]
open close high low
2018-02-27 23.53 24.16 25.88 23.53
2018-02-26 22.80 23.53 23.78 22.80
2018-02-23 22.88 22.82 23.37 22.71
2018-02-22 22.25 22.28 22.76 22.02
赋值操作
对DataFrame当中的close列进行重新赋值为1
# 直接修改原来的值
data['close'] = 1
# 或者
data.close = 1
排序操作
排序有两种形式,一种对于索引进行排序,一种对于内容进行排序
- 使用df.sort_values(by=, ascending=)
- 单个键或者多个键进行排序,默认升序
- ascending=False:降序
- ascending=True:升序
- 单个键或者多个键进行排序,默认升序
# 按照涨跌幅大小进行排序 , 使用ascending指定按照大小排序
data = data.sort_values(by='p_change', ascending=False).head()
open high close low volume price_change p_change turnover
2015-08-28 15.40 16.46 16.46 15.00 117827.60 1.50 10.03 4.03
2015-05-21 27.50 28.22 28.22 26.50 121190.11 2.57 10.02 4.15
2016-12-22 18.50 20.42 20.42 18.45 150470.83 1.86 10.02 3.77
2015-08-04 16.20 17.35 17.35 15.80 94292.63 1.58 10.02 3.23
2016-07-07 18.66 18.66 18.66 18.41 48756.55 1.70 10.02 1.67
# 按照过个键进行排序
data = data.sort_values(by=['open', 'high'])
open high close low volume price_change p_change turnover
2015-06-15 34.99 34.99 31.69 31.69 199369.53 -3.52 -10.00 6.82
2015-06-12 34.69 35.98 35.21 34.01 159825.88 0.82 2.38 5.47
2015-06-10 34.10 36.35 33.85 32.23 269033.12 0.51 1.53 9.21
2017-11-01 33.85 34.34 33.83 33.10 232325.30 -0.61 -1.77 5.81
2015-06-11 33.17 34.98 34.39 32.51 173075.73 0.54 1.59 5.92
- 使用df.sort_index给索引进行排序
# 对索引进行排序
data.sort_index()
open high close low volume price_change p_change turnover
2015-03-02 12.25 12.67 12.52 12.20 96291.73 0.32 2.62 3.30
2015-03-03 12.52 13.06 12.70 12.52 139071.61 0.18 1.44 4.76
2015-03-04 12.80 12.92 12.90 12.61 67075.44 0.20 1.57 2.30
2015-03-05 12.88 13.45 13.16 12.87 93180.39 0.26 2.02 3.19
2015-03-06 13.17 14.48 14.28 13.13 179831.72 1.12 8.51 6.16
DataFrame运算
算数运算
# 加add ,减sub,乘mul,除div
data['low'].add(10).head()
data['high'].sub(data['close'])
逻辑运算
<、 >、|、 &
data['p_change'] > 2
2018-02-27 True
2018-02-26 True
2018-02-23 True
2018-02-22 False
2018-02-14 True
# 逻辑判断的结果可以作为筛选的依据
data[data['p_change'] > 2]
pen high close low volume price_change p_change turnover my_price_change
2018-02-27 23.53 25.88 24.16 23.53 95578.03 0.63 2.68 2.39 0.63
2018-02-26 22.80 23.78 23.53 22.80 60985.11 0.69 3.02 1.53 0.73
2018-02-23 22.88 23.37 22.82 22.71 52914.01 0.54 2.42 1.32 -0.06
2018-02-14 21.49 21.99 21.92 21.48 23331.04 0.44 2.05 0.58 0.43
2018-02-12 20.70 21.40 21.19 20.63 32445.39 0.82 4.03 0.81 0.49
完成一个多个逻辑判断, 筛选p_change > 2并且open > 15
data[(data['p_change'] > 2) & (data['open'] > 15)]
open high close low volume price_change p_change turnover my_price_change
2017-11-14 28.00 29.89 29.34 27.68 243773.23 1.10 3.90 6.10 1.34
2017-10-31 32.62 35.22 34.44 32.20 361660.88 2.38 7.42 9.05 1.82
2017-10-27 31.45 33.20 33.11 31.45 333824.31 0.70 2.16 8.35 1.66
2017-10-26 29.30 32.70 32.41 28.92 501915.41 2.68 9.01 12.56 3.11
逻辑运算函数
- query(expr)
- expr:查询字符串
通过query使得刚才的过程更加方便简单
data.query("p_change > 2 & turnover > 15")
isin(values)
例如判断'turnover'是否为4.19, 2.39
# 可以指定值进行一个判断,从而进行筛选操作
data[data['turnover'].isin([4.19, 2.39])]
open high close low volume price_change p_change turnover my_price_change
2018-02-27 23.53 25.88 24.16 23.53 95578.03 0.63 2.68 2.39 0.63
2017-07-25 23.07 24.20 23.70 22.64 167489.48 0.67 2.91 4.19 0.63
2016-09-28 19.88 20.98 20.86 19.71 95580.75 0.98 4.93 2.39 0.98
2015-04-07 16.54 17.98 17.54 16.50 122471.85 0.88 5.28 4.19 1.00
统计运算
data.describe()
综合分析: 能够直接得出很多统计结果,count, mean, std, min, max 等
min(最小值), max(最大值), mean(平均值), median(中位数), var(方差), std(标准差),mode(众数)
# 使用统计函数:0 代表列求结果, 1 代表行求统计结果
data.max(0)
open 34.99
high 36.35
close 35.21
low 34.01
volume 501915.41
price_change 3.03
p_change 10.03
turnover 12.56
my_price_change 3.41
dtype: float64
median():中位数
中位数为将数据从小到大排列,在最中间的那个数为中位数。如果没有中间数,取中间两个数的平均值。
df = pd.DataFrame({'COL1' : [2,3,4,5,4,2],
'COL2' : [0,1,2,3,4,2]})
df.median()
COL1 3.5
COL2 2.0
dtype: float64
idxmax()、idxmin()
# 求出最大值的位置
data.idxmax(axis=0)
open 2015-06-15
high 2015-06-10
close 2015-06-12
low 2015-06-12
volume 2017-10-26
price_change 2015-06-09
p_change 2015-08-28
turnover 2017-10-26
my_price_change 2015-07-10
dtype: object
# 求出最小值的位置
data.idxmin(axis=0)
open 2015-03-02
high 2015-03-02
close 2015-09-02
low 2015-03-02
volume 2016-07-06
price_change 2015-06-15
p_change 2015-09-01
turnover 2016-07-06
my_price_change 2015-06-15
dtype: object
累计统计函数
- cumsum 计算前1/2/3/…/n个数的和
- cummax 计算前1/2/3/…/n个数的最大值
- cummin 计算前1/2/3/…/n个数的最小值
- cumprod 计算前1/2/3/…/n个数的积
data.head()
temp = data.sort_index(ascending=True)
# 统计累计求和值
res = temp['price_change'].cumsum()
# 绘制折线图
import matplotlib.pyplot as plt
res.plot()
plt.title('股票累计变化图')
plt.show()
自定义运算
- apply(func, axis=0)
- func:自定义函数
- axis=0:默认是列,axis=1为行进行运算
# 自定义函数
def fun_1(x):
return x.max()-x.min()
# apply(自定义函数名,axis=0即列/1即行)
data[['open','close']].apply(fun_1,axis=0)
或者
data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=0)
文件的读取与存储
pandas会支持复杂的IO操作,pandas的API支持众多的文件格式,如CSV、SQL、XLS、JSON、HDF5。
CSV
read_csv
- pandas.read_csv(filepath_or_buffer, sep =’,’ )
- filepath_or_buffer:文件路径
- usecols:指定读取的列名,列表形式
# 读取文件,并且指定只获取'open', 'close'指标
data = pd.read_csv("./data/stock_day.csv", usecols=['open', 'close'])
open high close
2018-02-27 23.53 25.88 24.16
2018-02-26 22.80 23.78 23.53
2018-02-23 22.88 23.37 22.82
2018-02-22 22.25 22.76 22.28
2018-02-14 21.49 21.99 21.92
to_csv
- DataFrame.to_csv(path_or_buf=None, sep=’, ’, columns=None, header=True, index=True, mode=‘w’, encoding=None)
- path_or_buf :string or file handle, default None
- sep :character, default ‘,’
- columns :sequence, optional
- mode:‘w’:重写, ‘a’ 追加
- index:是否写进行索引
- header :boolean or list of string, default True,是否写进列索引值
HDF5
ead_hdf与to_hdf
HDF5文件的读取和存储需要指定一个键,值为要存储的DataFrame
从h5文件当中读取数据
- pandas.read_hdf(path_or_buf,key =None,** kwargs)
- path_or_buffer:文件路径
- key:读取的键
- return:Theselected object
向h5文件当中写入数据
- DataFrame.to_hdf(path_or_buf, key, \kwargs)
案例
读取文件
day_eps_ttm = pd.read_hdf("./data/stock_data/day/day_eps_ttm.h5")
如果读取的时候出现以下错误
需要安装安装tables模块避免不能读取HDF5文件
pip install tables
存储文件
day_eps_ttm.to_hdf("./data/test.h5", key="day_eps_ttm")
再次读取的时候, 需要指定键的名字
new_eps = pd.read_hdf("./data/test.h5", key="day_eps_ttm")
优先选择使用HDF5文件存储
- HDF5在存储的时候支持压缩,使用的方式是blosc,这个是速度最快的也是pandas默认支持的
- 使用压缩可以提磁盘利用率,节省空间
- HDF5还是跨平台的,可以轻松迁移到hadoop 上面
JSON
read_json
- pandas.read_json(path_or_buf=None, orient=None, typ=‘frame’, lines=False)
- 将JSON格式转换成默认的Pandas DataFrame格式
- orient : string,Indication of expected JSON string format.
- ‘split’ : dict like {index -> [index], columns -> [columns], data -> [values]}
- split 将索引总结到索引,列名到列名,数据到数据。将三部分都分开了
- ‘records’ : list like [{column -> value}, … , {column -> value}]
- records 以columns:values的形式输出
- ‘index’ : dict like {index -> {column -> value}}
- index 以index:{columns:values}…的形式输出
- ‘columns’ : dict like {column -> {index -> value}},默认该格式
- colums 以columns:{index:values}的形式输出
- ‘values’ : just the values array
- values 直接输出值
- ‘split’ : dict like {index -> [index], columns -> [columns], data -> [values]}
- lines : boolean, default False
- 按照每行读取json对象
- typ : default ‘frame’, 指定转换成的对象类型series或者dataframe
read_josn 案例
数据介绍
这里使用一个新闻标题讽刺数据集,格式为json。is_sarcastic:1讽刺的,否则为0;headline:新闻报道的标题;article_link:链接到原始新闻文章。存储格式为:
{"article_link": "https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5", "headline": "former versace store clerk sues over secret 'black code' for minority shoppers", "is_sarcastic": 0}
{"article_link": "https://www.huffingtonpost.com/entry/roseanne-revival-review_us_5ab3a497e4b054d118e04365", "headlin
读取
orient指定存储的json格式,lines指定按照行去变成一个样本
json_read = pd.read_json("./data/Sarcasm_Headlines_Dataset.json", orient="records", lines=True)
to_json
- DataFrame.to_json(path_or_buf=None, orient=None, lines=False)
- 将Pandas 对象存储为json格式
- path_or_buf=None:文件地址
- orient:存储的json形式,{‘split’,’records’,’index’,’columns’,’values’}
- lines:一个对象存储为一行
to_json 案例
json_read.to_json("./data/test.json", orient='records')
结果
[{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0},{"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1},{"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/advancing-the-worlds-women_b_6810038.html","headline":"advancing the world's women","is_sarcastic":0},....]
修改lines参数为True
json_read.to_json("./data/test.json", orient='records', lines=True)
结果
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0}
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0}
{"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1}
{"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1}
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0}...
缺失值处理
缺失值nan
判断数据是否为NaN:
- pd.isnull(df)
- pd.notnull(df)
处理方式:
-
存在缺失值nan,并且是np.nan:
- 删除存在缺失值的:dropna(axis=‘rows’)
注:不会修改原数据,需要接受返回值 - 替换缺失值:fillna(value, inplace=True)
- value:替换成的值
- inplace:True:会修改原数据,False:不替换修改原数据,生成新的对象
- 删除存在缺失值的:dropna(axis=‘rows’)
-
不是缺失值nan,有默认标记的
案例
import pandas as pd
import numpy as np
# 缺失值处理
data = pd.read_csv('/home/python/Desktop/test_data/IMDB-Movie-Data.csv')
# 判断是否有缺失
res = pd.isnull(data) # 判断每个元素是否是NaN
# 判断是否有True
np.any(res)
# 判断是否有缺失
res_2 = pd.notnull(data) # 判断每个元素是否不是NaN
np.all(res_2) # 判断是否全为True
存在缺失值nan,并且是np.nan
# 1.删除缺失值 dropna 删除有缺失的整行,不修改原数据
data.dropna()
# 2.替换/填充缺失值 fillna 填充平均值或者中位数
data.fillna(value=data.mean())
不是缺失值nan,有默认标记的
读取数据
wis = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data")
若如下错误:
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)>
解决办法:
# 全局取消证书验证
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
特殊标记缺失值处理方法:
- 先替换‘?’为np.nan
df.replace(to_replace=, value=)- to_replace:替换前的值
- value:替换后的值
- 进行np.nan缺失值的处理
# 删除
wis = wis.dropna()
数据离散化
连续属性离散化的目的是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具。
连续属性的离散化就是在连续属性的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数 值代表落在每个子区间中的属性值。
离散化有很多种方法,这使用一种最简单的方式去操作
- 原始人的身高数据:165,174,160,180,159,163,192,184
- 假设按照身高分几个区间段:150~165, 165~180,180~195
这样我们将数据分到了三个区间段,我可以对应的标记为矮、中、高三个类别,最终要处理成一
个"哑变量"矩阵
哑变量(Dummy Variable),又称为虚拟变量、虚设变量或名义变量,从名称上看就知道,它是人为虚设的变量,通常取值为0或1,来反映某个变量的不同属性。
Dummy Coding
import pandas as pd
# 读取数据
data = pd.read_csv('/home/python/Desktop/test_data/stock_day.csv')
data.head()
# 取出p_change列
p_change = data['p_change']
# 进行数据离散化 qcut(离散化的数据,组数,labels=新组名),qcut将数据平均分到指定数量的类别中
res = pd.qcut(p_change,3,labels=['A','B','C'])
res.value_counts() # 统计离散化的各个结果数量
# 指定区间划分
bins = [-100,-7,-3,0,3,7,100]
res3 = pd.cut(p_change,bins)
res3.value_counts() # 统计离散化的各个结果数量
one-hot编码
把每个类别生成一个布尔列,这些列中只有一列可以为这个样本取值为1.其又被称为热编码。
pandas.get_dummies(data, prefix=None)
- data:array-like, Series, or DataFrame
- prefix:分组名字
# 得出one-hot编码矩阵
dummies = pd.get_dummies(p_counts, prefix="rise")
合并
pd.concat实现数据合并
- pd.concat([data1, data2], axis=1)
- 按照行或列进行合并,axis=0为列索引,axis=1为行索引
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 读取数据
data = pd.read_csv('/home/python/Desktop/test_data/stock_day.csv')
# 获取p_change列
p_change = data['p_change']
# 离散化
res = pd.qcut(p_change,3)
res.value_counts()
# one-hot编码
res2 = pd.get_dummies(res,prefix='abc')
res2
# 数据集合并 axis=1 按列合并,axis=0按行合并
pd.concat([data,res2],axis=1)
pd.merge
-
pd.merge(left, right, how=‘inner’, on=None, left_on=None, right_on=None)
- 可以指定按照两组数据的共同键值对合并或者左右各自
- left: A DataFrame object
- right: Another DataFrame object
- on: Columns (names) to join on. Must be found in both the left and right DataFrame objects.
- left_on=None, right_on=None:指定左右键
-
内连接
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
# 默认内连接
result = pd.merge(left, right, on=['key1', 'key2'])
- 左连接
result = pd.merge(left, right, how='left', on=['key1', 'key2'])
- 右连接
result = pd.merge(left, right, how='right', on=['key1', 'key2'])
- 外链接
result = pd.merge(left, right, how='outer', on=['key1', 'key2'])
交叉表与透视表
交叉表
交叉表(cross-tabulation, 简称crosstab)是一种用于计算分组频率的特殊透视表.
交叉表是寻找两列之间的关系,按第一列的分组的同时,继续按 第2列分组,并统计个数。
data.head()
# 探究股票涨跌与星期几有关
pd.to_datetime(data.index).weekday # 0为周一
# 添加新一列并赋值
data['week'] = pd.to_datetime(data.index).weekday
data.head()
# 创建新一列记录涨跌,通过np.where 更改True为1,False为0
data['rise'] = np.where(data['p_change']>0,1,0)
data.head()
# 建立交叉表 两列离散数据
temp = pd.crosstab(data['rise'],data['week'])
temp
# 按列求和
sum_date = temp.sum(axis=0)
sum_date
# 计算每周上涨下跌概率 63/125=0.504
res = temp.div(sum_date,axis=1)
res
# 绘制柱状图
res = res.T # 取数据时候,行列位置颠倒,因此先转置
res.plot(kind='bar',stacked=True)
plt.show()
透视表
各种电子表格程序和其他数据分析软件中一种常见的数据汇总工具。它根据一个或多个键对数据进行聚合,并根据行和列上的分组键将数据分配到各个矩形区域中。
透视表就是将指定原有DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数(默认情况下式mean函数)。
pivot_table(data,index,colums,values,aggfunc,fill_value,margins,margins_name=)
- index: 行索引
- colums: 列索引
- values: 分组的字段,只能为数值型变量
- aggfunc: 聚合函数
- fill_value: 缺失值填充方法
- margins: 是否需要总计
# 用透视表计算涨跌概率 透视表一般用来分组和聚合
pd.pivot_table(data=data,index='week',values='rise',aggfunc='mean')
分组与聚合
分组
DataFrame.groupby(key, as_index=False)
- key:分组的列数据,可以多个
import pandas as pd
import matplotlib.pyplot as plt
col =pd.DataFrame({'color': ['white','red','green','red','green'], 'object': ['pen','pencil','pencil','ashtray','pen'],'price1':[5.56,4.20,1.30,0.56,2.75],'price2':[4.75,4.12,1.60,0.75,3.15]})
color object price1 price2
0 white pen 5.56 4.75
1 red pencil 4.20 4.12
2 green pencil 1.30 1.60
3 red ashtray 0.56 0.75
4 green pen 2.75 3.15
分组,求平均数
col.groupby(['color'])['price1'].mean()
col['price1'].groupby(col['color']).mean()
分组数据结构不变
# 分组
col.groupby(['color'],as_index=False)['price1'].mean()
分组数据结构改变
as_index 的默认值为True, 对于聚合输出,返回以组标签作为索引的对象。仅与DataFrame输入相关。as_index = False实际上是“SQL风格”的分组输出。
- 当as_index=True时,没有显示索引项,而是以第一列组标签为索引值
- 当as_index=False时,显示索引项,此时可以通过df.iloc[0]取得值
案例
数据来源
# 导入星巴克店的数据
starbucks = pd.read_csv("./data/starbucks/directory.csv")
starbucks
进行分组聚合
# 按照国家分组,求出每个国家的星巴克零售店数量
count = starbucks.groupby(['Country']).count()
画图显示结果
count['Brand'].plot(kind='bar', figsize=(20, 8))
plt.show()
假设我们加入省市一起进行分组
# 设置多个索引,set_index()
starbucks.groupby(['Country', 'State/Province']).count()
案例
# %matplotlib inline # 内嵌图像到jupyter中,省略plt.show()
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
file_path = '/home/python/Desktop/test_data/IMDB-Movie-Data.csv'
df = pd.read_csv(file_path)
df
# 评分的平均分
df['Rating'].mean()
6.723199999999999
# 得出导演人数信息
df['Director']
# 导演去重
res = df['Director'].unique()
# np.unique(df['Director'])
# 获取导演数量
res.size
644
# 获取Rating的分布情况
df['Rating'].plot(kind='hist',figsize=(20,8),bins=20)
# 修改直方图的x轴刻度,以最大到最小划分为21个区间
plt.xticks(np.linspace(df['Rating'].min(),df['Rating'].max(),21))
# 添加网格线
plt.grid()
plt.show()
# # 设置刻度的第二种方法
# res = df['Rating'].plot(kind='hist',figsize=(20,8),bins=20)
# plt.xticks(res[1])
# 电影分类gener中每个有多个类别,先获取
df['Genre']
# 遍历获取每个类别并存入列表中
temp_list = list()
temp_list = [i.split(',') for i in df['Genre']]
temp_list
# 数组去重
genre_list = [j for i in temp_list for j in i]
genre_temp = np.unique(genre_list)
genre_temp
# 构建一个记录电影类型数量的容器 Series
genre_s = pd.Series(np.zeros((len(genre_temp),)),index=genre_temp)
genre_s
# 遍历temp_list,出现一次类型,Series中+1
for i in temp_list:
for j in i:
genre_s[j] +=1
genre_s
# 绘制图像
genre_s.plot(kind='bar',figsize=(20,8))
plt.show()
Seaborn
Seaborn其实是在matplotlib的基础上进行了更高级的API封装,从而使得作图更加容易,在大多数情况下使用seaborn就能做出很具有吸引力的图,而使用matplotlib就能制作具有更多特色的图。应该把Seaborn视为matplotlib的补充,而不是替代物。
- Python中的一个制图工具库,可以制作出吸引人的、信息量大的统计图
- 在Matplotlib上构建,支持numpy和pandas的数据结构可视化。
- 多个内置主题及颜色主题
- 可视化单一变量、二维变量用于比较数据集中各变量的分布情况
- 可视化线性回归模型中的独立变量及不独立变量
import numpy as np
import pandas as pd
# from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# %matplotlib inline
单变量分布 sns.distplot()
# 单变量分布
x1 = np.random.normal(size=1000)
sns.distplot(x1);
x2 = np.random.randint(0, 100, 500)
sns.distplot(x2);
直方图 sns.distplot(kde=False)
# 直方图
sns.distplot(x1, bins=20, kde=False, rug=True)
核密度估计 sns.distplot(hist=False) 或 sns.kdeplot()
# 核密度估计
sns.distplot(x2, hist=False, rug=True)
双变量分布
# 双变量分布
df_obj1 = pd.DataFrame({"x": np.random.randn(500),
"y": np.random.randn(500)})
df_obj2 = pd.DataFrame({"x": np.random.randn(500),
"y": np.random.randint(0, 100, 500)})
散布图 sns.jointplot()
# 散布图
sns.jointplot(x="x", y="y", data=df_obj1)
二维直方图 Hexbin sns.jointplot(kind=‘hex’)
# 二维直方图
sns.jointplot(x="x", y="y", data=df_obj1, kind="hex");
核密度估计 sns.jointplot(kind=‘kde’)
# 核密度估计
sns.jointplot(x="x", y="y", data=df_obj1, kind="kde");
数据集中变量间关系可视化 sns.pairplot()
# 数据集中变量间关系可视化
dataset = sns.load_dataset("tips")
#dataset = sns.load_dataset("iris")
sns.pairplot(dataset);
类别散布图
sns.stripplot() 数据点会重叠
sns.stripplot(x="diet", y="pulse", data=exercise)
sns.swarmplot() 数据点避免重叠,hue指定子类别
sns.swarmplot(x="diet", y="pulse", data=exercise, hue='kind')
类别内数据分布
盒子图 sns.boxplot(), hue指定子类别
# 盒子图
sns.boxplot(x="diet", y="pulse", data=exercise)
#sns.boxplot(x="diet", y="pulse", data=exercise, hue='kind')
小提琴图 sns.violinplot(), hue指定子类别
# 小提琴图
#sns.violinplot(x="diet", y="pulse", data=exercise)
sns.violinplot(x="diet", y="pulse", data=exercise, hue='kind')
类别内统计图
柱状图 sns.barplot()
# 柱状图
sns.barplot(x="diet", y="pulse", data=exercise, hue='kind')
点图 sns.pointplot()
# 点图
sns.pointplot(x="diet", y="pulse", data=exercise, hue='kind');
更多推荐
所有评论(0)