科学计算库(一)

Jupyter Notebook、Matplotlib、Numpy

Posted by 新宇 on January 25, 2020

一、Jupyter Notebook

1. 介绍

Jupyter项目是一个非盈利的开源项目,源于2014年的ipython项目,因为它逐渐发展为支持跨所有编程语言的交互式数据科学和科学计算

  • Jupyter Notebook,原名IPython Notbook,是IPython的加强网页版,一个开源Web应用程序
  • 名字源自Julia、Python 和 R(数据科学的三种开源语言)
  • 是一款程序员和科学工作者的编程/文档/笔记/展示软件
  • .ipynb文件格式是用于计算型叙述的JSON文档格式的正式规范

2. 快捷键

  • 常用快捷键:
    • shift + enter 执行本单元代码,并跳转到下一单元
    • ctrl + enter 执行本单元代码,留在本单元
  • 命令模式:按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进入
    • 补全代码:变量、方法后跟 Tab键
    • 为一行或多行代码添加/取消注释: Ctrl+/ (Mac:CMD+/)
  • 其他(了解):
    • 多光标操作: Ctrl键点击鼠标 (Mac:CMD+点击鼠标)
    • 回退: Ctrl+Z (Mac:CMD+Z)
    • 重做: Ctrl+Y (Mac:CMD+Y)

3. 配置默认存储路径

# 首先在命令行窗口使用下面的命令生成并找到配置文件的位置:

jupyter notebook --generate-config
# 去掉261行的注释符#号,并修改c.NotebookApp.notebook_dir为自己指定的文件夹即可

c.NotebookApp.notebook_dir = '/Users/xxxx/jupyter-notebook-code'

# 重启jupyter notebook,即可发现,不管是在哪个地方启动jupyter notebook,它打开的都是 我们指定好的那个目录位置。

4. 使用Jupyter拓展功能

# 如果使用的是虚拟环境,主环境和虚拟环境都要安装jupyter ,和对应的扩展

# 1.一次执行下面的命令 pip install jupyter

python -m pip install jupyter_contrib_nbextensions
jupyter contrib nbextension install --user --skip-running-check

# 2.上述安装没问题的话,在主环境启动jupyter notebook,并在显示的页面上可以看到对应的拓展配 置选项卡

# 如下图

# 3.如果你勾选了autopep8,自动规范代码功能,需要安装依赖包

pip install autopep8

拓展选项卡:

二、Matplotlib

1. 概念

  • 是专门用于开发2D图表(包括3D图表),以渐进、交互式方式实现数据可视化
  • 能将数据进行可视化,更直观的呈现
  • 使数据更加客观、更具说服力

2. 基础绘图功能

import matplotlib.pyplot as plt import random
from pylab import mpl

# 设置显示中文字体 

mpl.rcParams["font.sans-serif"] = ["SimHei"] 
# 设置正常显示符号 

mpl.rcParams["axes.unicode_minus"] = False
# 0.准备数据

x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x]
# 1.创建画布

plt.figure(figsize=(20, 8), dpi=100)
# 2.绘制图像 plt.plot(x, y_shanghai)

# 2.1 添加x,y轴刻度

# 构造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])
# 2.2 添加网格显示

plt.grid(True, linestyle="--", alpha=0.5)
# 2.3 添加描述信息

plt.xlabel("时间")
plt.ylabel("温度") 
plt.title("中午11点--12点某城市温度变化图", fontsize=20)
# 2.4 图像保存 (注意:plt.show()会释放figure资源,如果在显示图像之后保存图片将只能保存空图片)

plt.savefig("./test.png")
# 3.图像显示 

plt.show()

3. 如何显示中文刻度

4. 绘制多行/列图像

# 0.准备数据

x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x] 
y_beijing = [random.uniform(1, 5) for i in x]
# 1.创建画布

fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 8), dpi=100)
# 2.绘制图像

axes[0].plot(x, y_shanghai, label="上海")
axes[1].plot(x, y_beijing, color="r", linestyle="--", label="北京")
# 2.1 添加x,y轴刻度

# 构造x,y轴刻度标签

x_ticks_label = ["11点{}分".format(i) for i in x] 
y_ticks = range(40)
# 刻度显示

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 添加网格显示

axes[0].grid(True, linestyle="--", alpha=0.5) 
axes[1].grid(True, linestyle="--", alpha=0.5)
# 2.3 添加描述信息

axes[0].set_xlabel("时间")
axes[0].set_ylabel("温度") 
axes[0].set_title("中午11点--12点某城市温度变化图", fontsize=20) 
axes[1].set_xlabel("时间")
axes[1].set_ylabel("温度") 
axes[1].set_title("中午11点--12点某城市温度变化图", fontsize=20)
# # 2.4 图像保存 

plt.savefig("./test.png")
# # 2.5 添加图例

axes[0].legend(loc=0) 
axes[1].legend(loc=0)
# 3.图像显示 

plt.show()

5. 绘制sin(x)

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()

6. 常见图形绘制

折线图、散点图、柱状图、直方图、饼图

1. 散点图绘制

 # 0.准备数据
    
x = [225.98, 247.07, 253.14, 457.85, 241.58, 301.01, 20.67, 288.64,
163.56, 120.06, 207.83, 342.75, 147.9 , 53.06, 224.72, 29.51, 21.61, 483.21, 245.25, 399.25, 343.35]
y = [196.63, 203.88, 210.75, 372.74, 202.41, 247.61, 24.9 , 239.34, 140.32, 104.15, 176.84, 288.23, 128.79, 49.64, 191.74, 33.1 ,
30.74, 400.02, 205.35, 330.64, 283.45] 
# 1.创建画布

plt.figure(figsize=(20, 8), dpi=100) 
# 2.绘制散点图

plt.scatter(x, y)
# 3.显示图像 

plt.show()

2. 柱状图绘制

# 0.准备数据

# 电影名字

movie_name = ['雷神3:诸神黄昏','正义联盟','东方快车谋杀案','寻梦环游记','全球风暴','降魔传','追捕','七十七天','密战','狂兽','其它']

# 横坐标

x = range(len(movie_name))
# 票房数据

y = [73853,57767,22354,15969,14839,8725,8716,8318,7916,6764,52222]
# 1.创建画布

plt.figure(figsize=(20, 8), dpi=100)
# 2.绘制柱状图

plt.bar(x, y, width=0.5, color=['b','r','g','y','c','m','y','k','c','g','b'])
# 2.1b修改x轴的刻度显示 

plt.xticks(x, movie_name)
# 2.2 添加网格显示 

plt.grid(linestyle="--", alpha=0.5)
# 2.3 添加标题 

plt.title("电影票房收入对比")
# 3.显示图像 

plt.show()

3. 其他图参考

matplotlib官网

  • 折线图:能够显示数据的变化趋势,反映事物的变化情况。(变化) plt.plot()
  • 散点图:判断变量之间是否存在数量关联趋势,展示离群点(分布规律) plt.scatter()
  • 柱状图:绘制连离散的数据,能够一眼看出各个数据的大小,比较数据之间的差别。(统计/对比) plt.bar(x, width, align=”center”)
  • 直方图:绘制连续性的数据展示一组或者多组数据的分布状况(统计) plt.hist(x, bins)
  • 饼图:用于表示不同分类的占比情况,通过弧度大小来对比各种分类 plt.pie(x, labels, autopct, colors)

三、Numpy

1. 概念

  • Numpy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。
  • Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。
  • Numpy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器。

2. ndarray介绍

1. 概念

NumPy提供了一个N维数组类型ndarray,它描述了相同类型的“items”的集合。

2. 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)

## 结果对比:

# CPU times: user 831 ms, sys: 1.8 s, total: 2.63 s

# Wall time: 2.74 s

# CPU times: user 56.3 ms, sys: 335 µs, total: 56.6 ms

# Wall time: 56.4 ms

3. ndarray原理

  1. 内存模型
  2. 支持并行化运算:numpy内置了并行运算功能,当系统有多个核心时,做某种计算时,numpy会自动做并行计算
  3. 效率远高于纯Python代码:Numpy底层使用C语言编写,内部解除了GIL(全局解释器锁),其对数组的操作速度不受Python解释器的限制,所以,其效率远高于纯Python代码。

4. ndarray属性介绍

5. ndarray的类型

6. 代码

# 创建数组时指定类型
a = np.array([[1, 2, 3],[4, 5, 6]], dtype=np.float32) >>> a.dtype

arr = np.array(['python', 'tensorflow', 'scikit-learn', 'numpy'], dtype = np.string_) 

3. numpy快速创建数组

1. 生成0和1的数组

  • np.ones(shape, dtype)
  • np.ones_like(a, dtype)
  • np.zeros(shape, dtype)
  • np.zeros_like(a, dtype)

2. 从现有数组生成

  • 从现有数组生成
    • 深拷贝:np.array(object, dtype)
    • 赋值:np.asarray(a, dtype)
  • 生成固定范围的数组
    • 创建等差数组 — 指定数量: np.linspace (start, stop, num, endpoint)
    • 创建等差数组 — 指定步长:np.arange(start,stop, step, dtype)
    • 创建等比数列:np.logspace(start,stop, num)

4. 生成随机数组

np.random模块

1. 正态分布

  1. 概念:正态分布是一种概率分布。正态分布是具有两个参数μ和σ的连续型随机变量的分布,第一参数μ是服从正态分布的随机变量的均值,第二个参数σ是此随机变量的标准差,所以正态分布记作N(μ,σ)。

  2. 创建方式:
    • 标准正态分布: np.random.randn(d0, d1, …, dn)
    • 指定正态分布:np.random.normal(loc=0.0, scale=1.0, size=None)
    • 指定形状的标准正态分布:np.random.standard_normal(size=None)
  3. 代码

     # 生成均值为1.75,标准差为1的正态分布数据,100000000个
    
     x1 = np.random.normal(1.75, 1, 100000000)
    
     # 生成均匀分布的随机数
    
     x1 = np.random.normal(1.75, 1, 100000000)
     # 画图看分布状况
    
     # 1)创建画布
    
     plt.figure(figsize=(20, 10), dpi=100)
     # 2)绘制直方图 
    
     plt.hist(x1, 1000)
     # 3)显示图像 
    
     plt.show()
    

2. 均匀分布

  1. 创建方式
    • 返回[0.0,1.0)内的一组均匀分布的数:
      • np.random.rand(d0, d1, …, dn)
    • 一个均匀分布[low,high)中随机采样:
      • np.random.uniform(low=0.0, high=1.0, size=None)
    • 一个均匀分布中随机采样,生成一个整数或N维整数数组:
      • np.random.randint(low, high=None, size=None, dtype=’l’)
  2. 代码

     x2 = np.random.uniform(0,10,1000000)
     plt.figure(figsize=(20,8), dpi=100)
     # x代表要使用的数据,bins表示要划分区间数
    
     plt.hist(x2,bins=1000)
     plt.show()
    

3. 数组的索引、切片

  1. 一维、二维、三维的数组如何索引?
    • 直接进行索引,切片
    • 对象[:, :] – 先行后列
  2. 代码

     stock_change[0,0:3]
    

4. 形状修改

  • 返回一个具有相同数据域,但shape不一样的视图:
    • ndarray.reshape(shape, order)
  • 修改数组本身的形状(需要保持元素个数前后相同):
    • ndarray.resize(new_shape)
  • 数组的转置
    • ndarray.T
    • ndarray.transpose()

5. 类型修改

  • 返回修改了类型之后的数组
    • ndarray.astype(type)
  • 构造包含数组中原始数据字节的Python字节
    • ndarray.tostring([order])
    • ndarray.tobytes([order])

6. 数组的去重

  • np.unique()
temp = np.array([[1, 2, 3, 4],[3, 4, 5, 6]])
# >>> np.unique(temp)

array([1, 2, 3, 4, 5, 6])

5. ndarray运算

1. 逻辑运算

 # 生成10名同学,5门功课的数据

>>> score = np.random.randint(40, 100, (10, 5))
# 取出最后4名同学的成绩,用于逻辑判断 

>>> test_score = score[6:, 0:5]
# 逻辑判断, 如果成绩大于60就标记为True 否则为False

>>> test_score > 60
array([[ True, True, True, False, True],
[ True, True, True, False, True], [ True, True, False, False, True], [False, True, True, True, True]])
# BOOL赋值, 将满足条件的设置为指定的值-布尔索引 

>>> test_score[test_score > 60] = 1
>>> test_score
array([[ 1, 1, 1, 52, 1],
[1, 1, 1,59, 1], [ 1, 1, 44, 44, 1], [59, 1, 1, 1, 1]])

2. 通用判断函数

# 判断前两名同学的成绩[0:2, :]是否全及格 

np.all(score[0:2, :] > 60)
False
# 判断前两名同学的成绩[0:2, :]是否有大于90分的 

np.any(score[0:2, :] > 80)
True

3. np.where(三元运算符)

# 判断前四名学生,前四门课程中,成绩中大于60的置为1,否则为0 

temp = score[:4, :4]
np.where(temp > 60, 1, 0)

# 复合逻辑需要结合np.logical_and和np.logical_or使用

# 判断前四名学生,前四门课程中,成绩中大于60且小于90的换为1,否则为0 

 np.where(np.logical_and(temp > 60, temp < 90), 1, 0)
# 判断前四名学生,前四门课程中,成绩中大于90或小于60的换为1,否则为0 

np.where(np.logical_or(temp > 90, temp < 60), 1, 0)

4. 统计运算

  • min(a, axis)
  • max(a, axis])
  • median(a, axis)
    • 求中位数
  • mean(a, axis, dtype)
    • 求平均数
  • std(a, axis, dtype)
    • 标准差
  • var(a, axis, dtype)
    • 方差
  • argmax()
    • 返回最大值所在的索引
  • argmin()
    • 返回最小值所在的索引
# 接下来对于前四名学生,进行一些统计运算

# 指定列 去统计

temp = score[:4, 0:5] 
print("前四名学生,各科成绩的最大分:{}".format(np.max(temp, axis=0))) 
print("前四名学生,各科成绩的最小分:{}".format(np.min(temp, axis=0))) 
print("前四名学生,各科成绩波动情况:{}".format(np.std(temp, axis=0))) 
print("前四名学生,各科成绩的平均分:{}".format(np.mean(temp, axis=0)))

6. 数组间运算

1. 数组与数的运算

arr = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]]) 
arr + 1
arr / 2
# 可以对比python列表的运算,看出区别 a = [1, 2, 3, 4, 5]

a*3

2. 数组与数组的运算

  1. 广播机制:数组在进行矢量化运算时,要求数组的形状是相等的。当形状不相等的数组执行算术运算的时候,就会出现广播机制,该机制会对数组进行扩展,使数组的shape属性值一样,这样,就可以进行矢量化运算了。满足以下任意一个条件即可:
    • 如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符
    • 或其中的一方的长度为1。
  2. 代码
      arr1 = np.array([[0],[1],[2],[3]]) arr1.shape
     # (4, 1)
    
     arr2 = np.array([1,2,3]) arr2.shape
     # (3,)
    
     arr1+arr2
     # 结果是: array([[1, 2, 3],
    
     [2, 3, 4],
     [3, 4, 5],
     [4, 5, 6]])
    

7. 矩阵运算

这部分只介绍乘法API:np.matmul 和 np.dot

  1. np.matmul和np.dot的区别: 二者都是矩阵乘法。 np.matmul中禁止矩阵与标量的乘法。 在矢量乘矢量的內积运算中,np.matmul与np.dot没有区别。

  2. 代码

      >>> 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]])