Python数据处理
¶

04. numpy, scipy and matplotlib
¶

主讲人:丁平尖

python中的数值计算:numpy¶

  • Matlab的免费竞争对手之一
  • Numpy快速入门指南
    • https://numpy.org/doc/2.1/user/absolute_beginners.html
  • Matlab和Numpy对比
    • https://numpy.org/devdocs/user/numpy-for-matlab-users.html
  • 安装numpy包的方法:
    • 在conda命令行:conda install numpy

numpy数据类型¶

  • 五种基本数值数据类型:
    • 布尔(bool)
    • 整数(int)
    • 无符号整数(uint)
    • 浮点数(float)
    • 复数(complex)
  • 更多复杂的数据类型:
    • https://numpy.org/doc/stable/user/basics.types.html
In [2]:
import numpy as np #导入numpy模块,并给于一个更短的名字
y = np.float32(3.1415)
z = 1+2j
type(y), type(z)
Out[2]:
(numpy.float32, complex)
In [112]:
x = np.float64(3.1415)
x == y, x==np.float64(y), y==np.float32(x)
Out[112]:
(np.False_, np.False_, np.True_)
In [97]:
y == np.float32(x)
Out[97]:
np.True_

numpy.array:numpy的Python数组版本(即,列表)¶

  • 创建np.array
In [98]:
# 利用Python列表创建np.array
x = np.array([1, 2, 3], dtype='uint')
x
Out[98]:
array([1, 2, 3], dtype=uint64)
In [99]:
# 利用“shape”创建np.array
np.zeros((2,3))
Out[99]:
array([[0., 0., 0.],
       [0., 0., 0.]])
In [100]:
# 利用“range”创建np.array
np.arange(2, 3, 0.1, dtype='float')
Out[100]:
array([2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9])
  • numpy允许任意维度的数组(张量)
In [101]:
# 一维数组
x = np.arange(12)
x
Out[101]:
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
In [102]:
# 二维数组
x.shape = (3, 4)
x
Out[102]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
In [103]:
# 三维数组
x.shape = (2, 3, 2)
x
Out[103]:
array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5]],

       [[ 6,  7],
        [ 8,  9],
        [10, 11]]])

更多关于numpy.arange创建的信息¶

In [104]:
# np.arange(x):Python的range(x)的数组版本,类似于[0,1,2,...,x-1]
np.arange(10)
Out[104]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [105]:
# np.arange(x,y):Python的range(x,y)的数组版本,类似于[x,x+1,...,y-1]
np.arange(5, 10)
Out[105]:
array([5, 6, 7, 8, 9])
In [106]:
# np.arange(x,y,z):元素[x,y)的数组,以z大小的增量。
np.arange(0, 1, 0.1)
Out[106]:
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])

numpy阵列索引非常富有表现力¶

In [107]:
x = np.arange(10)
x[2:5], x[:-7], x[1:7:2], x[::2]
Out[107]:
(array([2, 3, 4]), array([0, 1, 2]), array([1, 3, 5]), array([0, 2, 4, 6, 8]))
In [108]:
x[x>7]
Out[108]:
array([8, 9])
In [109]:
x[(x>7) or  (x<2)]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[109], line 1
----> 1 x[(x>7) or  (x<2)]

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [34]:
# or 是一个逻辑运算符,用于连接两个布尔表达式。
# | 是一个按位或运算符,用于对两个整数进行二进制按位或运算。在 NumPy 中,| 还可以用于元素级别的逻辑或运算。
x[(x>7) |  (x<2)], x[(x<7) & (x>2)]
Out[34]:
(array([0, 1, 8, 9]), array([3, 4, 5, 6]))

布尔运算:np.logical_and()¶

In [35]:
x = np.arange(10)
np.logical_and(x>3, x<7), x[np.logical_and(x>3, x<7)]
Out[35]:
(array([False, False, False, False,  True,  True,  True, False, False,
        False]),
 array([4, 5, 6]))
In [36]:
np.logical_or(x<3, x>7), x[np.logical_or(x<3, x>7)]
Out[36]:
(array([ True,  True,  True, False, False, False, False, False,  True,
         True]),
 array([0, 1, 2, 8, 9]))
In [37]:
x[np.logical_xor(x>3, x<7)], x[np.logical_not(x>3)] 
Out[37]:
(array([0, 1, 2, 3, 7, 8, 9]), array([0, 1, 2, 3]))

numpy中的随机数¶

  • np.random包含生成随机数的方法
In [38]:
np.random.random((2, 3))
Out[38]:
array([[0.00453725, 0.39416826, 0.40793678],
       [0.60113822, 0.04869274, 0.42762343]])
In [39]:
np.random.random(5)
Out[39]:
array([0.5194481 , 0.53389005, 0.61865114, 0.04623146, 0.37280971])
In [40]:
np.random.uniform(1,3, 10)
Out[40]:
array([1.77041332, 1.46136309, 2.49111637, 2.053012  , 2.87388008,
       1.67722459, 1.17545697, 2.09851489, 1.54376765, 2.58335016])

np.random.choice():从数据中随机抽样¶

  • np.random.choice(x,[size,replace,p])
    • x: 要从中选择元素的数组或列表。
    • size: 选择的元素数量。如果省略,则返回单个元素。
    • replace: 是否允许重复选择同一个元素。默认为 True,即允许重复选择。
    • p: 每个元素被选择的概率。默认为 None,即所有元素被选择的概率相等。
In [41]:
x = np.arange(1, 11)
np.random.choice(x, 5, False, x/float(sum(x)))
Out[41]:
array([ 8, 10,  9,  5,  1])

shuffle()与permutation()¶

In [42]:
#返回x的随机排列,x保持不变。
np.random.permutation(x), x
Out[42]:
(array([ 5,  4,  3,  8,  6,  1,  2, 10,  9,  7]),
 array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10]))
In [43]:
# 随机地就地排列x的元素,所以x本身会被这个操作改变!
np.random.shuffle(x), x
Out[43]:
(None, array([10,  9,  3,  8,  2,  1,  6,  4,  7,  5]))

numpy中的统计¶

  • numpy实现了标准统计函数
In [44]:
x = np.random.normal(0, 1, 100) # 均值,标准差,形状
np.min(x), np.max(x), np.ptp(x)
Out[44]:
(np.float64(-3.074992077621176),
 np.float64(2.8019651926639453),
 np.float64(5.876957270285121))
In [45]:
np.std(x), np.var(x)
Out[45]:
(np.float64(1.0305924838012728), np.float64(1.0621208676676768))
  • numpy处理NaN(无效或未定义的数值)
In [46]:
x[5] = np.nan
np.mean(x)
Out[46]:
np.float64(nan)
In [47]:
np.nanmin(x), np.nanmax(x), np.nanstd(x), np.nanvar(x)
Out[47]:
(np.float64(-3.074992077621176),
 np.float64(2.8019651926639453),
 np.float64(1.0328581673396875),
 np.float64(1.066795993840298))

SciPy¶

  • SciPy(发音为“Sigh Pie”)广泛应用于数学、科学和工程领域。它包含了统计学、优化、积分、线性代数、傅里叶变换、信号与图像处理、常微分方程求解等多个模块。
    • https://docs.scipy.org/doc/scipy/tutorial/index.html#user-guide
    • 子模块
      • linalg: 线性代数
      • ndimage: N维图像处理
      • odr: 正交距离回归
      • optimize: 优化和求根算法
      • signal: 信号处理
      • sparse: 稀疏矩阵及相关程序
      • spatial: 空间数据结构与算法
      • special: 特殊函数
      • stats: 统计分布与函数
      • cluster: 聚类算法
      • constants: 物理和数学常数
      • fft: 离散傅里叶变换
      • fftpack: 快速傅里叶变换程序(旧版)
      • integrate: 积分与常微分方程求解器
      • interpolate: 插值与平滑样条
      • io: 输入和输出
In [48]:
# linalg: 线性代数
import numpy as np
from scipy.linalg import solve
# 定义系数矩阵 A
A = np.array([[3, 1], [1, 2]])
# 定义常数向量 b
b = np.array([9, 8])
# 求解线性方程组
x = solve(A, b)

print("解:", x)
解: [2. 3.]
In [49]:
# 用于求解非线性方程组的根,即找到函数输出值为零的输入值。
from scipy.optimize import root
from math import cos

def eqn(x):
  return x**2 -2

# hybr只会寻找离初始猜测值最近的根。
myroot1 = root(eqn, -1)
myroot2 = root(eqn, 1)
print(myroot1)
print('******************************************')
print(root(eqn, 1))
 message: The solution converged.
 success: True
  status: 1
     fun: [-8.882e-16]
       x: [-1.414e+00]
  method: hybr
    nfev: 10
    fjac: [[-1.000e+00]]
       r: [ 2.828e+00]
     qtf: [ 8.931e-10]
******************************************
 message: The solution converged.
 success: True
  status: 1
     fun: [-8.882e-16]
       x: [ 1.414e+00]
  method: hybr
    nfev: 10
    fjac: [[-1.000e+00]]
       r: [-2.828e+00]
     qtf: [ 8.931e-10]
In [50]:
# 用于求解非线性方程组的根,即找到函数输出值为零的输入值。
# 用于求解函数的最小值,即找到函数输出值最小的输入值。
from scipy.optimize import minimize

def eqn(x):
  return x**2 + x + 2

mymin = minimize(eqn, 10, method='BFGS')
print(mymin)
  message: Optimization terminated successfully.
  success: True
   status: 0
      fun: 1.7500000000000222
        x: [-5.000e-01]
      nit: 2
      jac: [ 3.129e-07]
 hess_inv: [[ 5.000e-01]]
     nfev: 8
     njev: 4
In [51]:
# sparse: 稀疏矩阵及相关程序
import scipy as sp
import numpy as np
dense = np.array([[1, 0, 0, 2], [0, 4, 1, 0], [0, 0, 5, 0]])
sparse = sp.sparse.coo_array(dense)
print(sparse)
print('****************************************')
print(sparse.todense())
<COOrdinate sparse array of dtype 'int64'
	with 5 stored elements and shape (3, 4)>
  Coords	Values
  (0, 0)	1
  (0, 3)	2
  (1, 1)	4
  (1, 2)	1
  (2, 2)	5
****************************************
[[1 0 0 2]
 [0 4 1 0]
 [0 0 5 0]]
In [52]:
# stats: 统计分布与函数
import scipy.stats as stats
# 生成两个独立样本的数据
np.random.seed(0)
a = np.random.normal(0, 1, 100)
b = np.random.normal(1, 1, 100)
# ttest_ind 是一个用于进行独立样本t检验的函数
# 用于比较两个独立样本的均值是否存在显著差异。
stats.ttest_ind(a, b)
Out[52]:
TtestResult(statistic=np.float64(-7.04142736901327), pvalue=np.float64(3.059820094514085e-11), df=np.float64(198.0))

matplotlib¶

  • https://matplotlib.org/stable/index.html

  • matplotlib.pyplot: 这是 Matplotlib 最常用的子模块,它提供了一个 MATLAB 风格的绘图接口,用于创建各种类型的图表。

In [63]:
# 折线图
import matplotlib.pyplot as plt
#Jupyter "magic" command to make images appear in-line
%matplotlib inline
x = np.arange(0, 5, 0.1, dtype='float')
plt.plot(x, x**2, color='red', linestyle=':', marker='o')
plt.xticks(x[::5])
_ = plt.show()
No description has been provided for this image
In [64]:
## multiple lines in a single plot
t = np.arange(0., 5., 0.2)
# plt.plot(x1vals, y1vals, traits1, x2val, y2vals, traits2, ...)
_ = plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
No description has been provided for this image
In [65]:
## Multiple lines in a single plot: long form
t = np.arange(0., 5., 0.2)
plt.grid()
plt.plot(t, t, 'r--')
plt.plot(t, t**2, 'bs')
plt.plot(t, t**3, 'g^')
_ = plt.show()
No description has been provided for this image
In [ ]:
 
In [66]:
# Titles and axis labels
t = np.arange(0., 5., 0.2)
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.title('Profits as a function of goats', fontsize=18)
plt.xlabel('Goats', fontsize=15)
plt.ylabel('Profits', fontsize=15)
_ = plt.show()
No description has been provided for this image
In [67]:
## Legends
# Can use LaTeX in labels, titles, etc
plt.xlabel("$n$", fontsize=16)
plt.ylabel("$f(n)$", fontsize=16)
plt.title("Different growth behaviors")
plt.plot(t, t, 'r--', label='linear, $f(n)=n$')
plt.plot(t, t**2, ':^r', label="quadratic, $f(n)=n^2$")
plt.plot(t, t**3, '--sg', label="cubic, $f(n)=n^3)$")
plt.legend(loc='best')
_ = plt.show()
No description has been provided for this image
In [110]:
## Annotating figures
t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
plt.plot(t, s, lw=2)
_ = plt.annotate('local max', xy=(2,1), xytext=(3, 1.5), fontsize=14, 
                 arrowprops=dict(facecolor='black', shrink=0.02))
No description has been provided for this image
In [69]:
## 直方图(Histogram)
mu, sigma = 100, 15
x = np.random.normal(mu, sigma, 10000)
(n, bins, patches) = plt.hist(x, bins=8, color='teal')
n, bins
Out[69]:
(array([  23.,  273., 1533., 3408., 3209., 1301.,  234.,   19.]),
 array([ 43.89849043,  58.03929203,  72.18009363,  86.32089523,
        100.46169683, 114.60249843, 128.74330003, 142.88410163,
        157.02490322]))
No description has been provided for this image
In [70]:
## 条形图(Bar Plot)
import string
t = np.arange(10)
s = np.random.normal(1, 1, 10)
mylabels = list(string.ascii_lowercase[0:len(t)])
_ = plt.bar(t, s, tick_label=mylabels, align='center')
No description has been provided for this image
In [71]:
## Box & whisker Plots (盒图)
K = 12; n = 25
draws = np.zeros((n, K))
means = np.zeros((n, 1))
for k in range(K):
    mu = np.sin(2*np.pi*k/K)
    draws[:,k] = np.random.normal(mu, 1, n)
print(draws.shape)
_ = plt.boxplot(draws, label=list('JFMAMJJASOND'))
(25, 12)
No description has been provided for this image
In [72]:
## 热图
n = 20
x = np.arange(1, n+1)
M = x * np.reshape(x, (n, 1))
_ = plt.imshow(M)
No description has been provided for this image
In [73]:
## 矩阵乘法函数和元素相乘函数
print(x.shape)
print(np.matmul(x, np.reshape(x, (n, 1))), x @ np.reshape(x, (n,1)))
np.multiply(x, np.reshape(x, (n, 1))) == x * np.reshape(x, (n, 1))
(20,)
[2870] [2870]
Out[73]:
array([[ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True,  True,  True,  True,  True,  True,  True,
         True,  True]])
In [113]:
## Subplots
# subplot(nrows, ncols, plot_number)
t = np.arange(20) + 1
plt.subplot(2, 2, 1); plt.plot(t, t, '-+b'); plt.title('linear')
plt.subplot(2, 2, 2); plt.plot(t, t**2, ':^r'); plt.title('quadratic')
plt.subplot(2, 2, 3); plt.plot(t, np.sqrt(t), '--sg'); plt.title('sqrt')
plt.subplot(2, 2, 4); plt.plot(t, np.log(t), '-oy'); plt.title('logarithmic')
_ = plt.tight_layout()
No description has been provided for this image
In [76]:
## Svaing images
plt.savefig("subplots.svg")
<Figure size 640x480 with 0 Axes>