numpy(numerical Python) 是 Python 数值计算最重要的基础包,大多数提供科学计算的包都是用 NumPy 的数组为构建基础。
NumPy 可以用于数值计算的一个重要原因是因为他能处理大数组的数据:

  • 在连续的内存块储存数据,独立于其他 Python 内置对象(C 语言编写的算法库,在 C 的基础上封装)
  • 可以在整个数组上执行复杂的计算,不需要 for loop

速查

687474703a2f2f7374617469632e7a7962756c756f2e636f6d2f5465616d2f696d336368356f647a3637766f7030706d707637396836382f6e702e706e67.png
图片对应pdf.pdf

介绍

基本用法

NumPy 最重要的一个特点就是 ndarray(n 维数组对象,一个快速而灵活的大数据集容器)

Creating ndarray

python 默认创建数组的数据类型是浮点数(方便科学计算)
image.png

  1. np.array():
  • 支持任何序列对象
  1. np.zeros()
  2. np.empty()创建一个数组,值可能为 0 有些情况下为垃圾值
  3. np.arrange():类似于内置的 range 返回一个

数组的数据类型

image.png

类型转换–np.astype

可以在创建数组时指定数值类型,也可以通过 np.astype()来转换数据类型(该函数会重新创建一个新的数组),除了用 np 里的数据类型,也可以用标准的数据类型,’<U4’好像是字符串。

import numpy as np
arr1=np.arange(6)
print(arr1.dtype)
arr2=arr1.astype(np.float64)
print(arr2.dtype)

数组形状

import numpy as np
# transposing and swaping
# 置换和交换
arr1 = np.arange(16).reshape(2, 2, 4)
print("="*40)
print(arr1)
print("="*40)
print(arr1.T)
print("="*40)
print(arr1.swapaxes(1, 2))
print("="*40)

Basic Indexing and Slicing

  • 索引利用’[]’,从 0 开始计数(相对于初始位置的偏移量)
  • ':'的运用,左闭右开区间
  • 切片产生的新数组仍然和原数组指向相同的储存位置(赋值操作)
  • Boolean Indexing
import numpy as np
# Boolean Indexing
name_arr = np.array(["xiaoming", "xiaohong", "xiaowang", "xiaoming"])
arr1 = np.random.randn(4, 6)

print("="*30)
print(arr1)
print("="*30)
# print(name_arr=="xiaoming")
print(arr1[name_arr == "xiaoming"])
#print(arr1[name_arr == "xiaoming"|name_arr=="xiaohong"])
#除了利用其他数组进行索引也可以用数组本身作为切片
#print(arr1[arr1<0])
print("="*30)

  • Fancy Indexing:直接使用数字表示行号进行索引查询

Where 函数

numpy.where函数能返回数组中符合条件的元素索引,这一点在获取数据集中特定类别的全部样本时非常有用。
numpy.where(condition,x,y)
其中 condition 接收条件表达式,值为 bool 型,若为 True 返回 x,否则返回 y
下面的语句将返回所有特征值小于 10 的样本索引:
numpy.where(X[:,0]<10)
根据返回的样本索引,可以找到这些索引的所有样本,进行分类别可视化等任务。

数组拼接

行拼接

numpy.hstack()

列拼接

numpy.vstack()

numpy.concatenate((a1, a2, ...), axis=0)
可指定数组横向组合还是纵向组合。

一维 n 列数组拼接组合成 n 维坐标点

numpy.c_[]
np.meshgrid()输入两个一维矩阵,输出二维坐标系(网格点)

读写文件

文章

随机数生成

np.random 和内置 random 一样可以用来生成符合任意概率分布的**伪随机数,**内置的 random 一次只生成一个随机数(大样本下速度会慢很多)。之所以叫做伪随机数是因为这种随机数是根据随机数生成器的种子形成的。我们可以通过np.random.seed()修改种子,这是一个全局变量。也可通过np.random.randomstate()创建一个隔离其他种子的随机种子。

rng=np.random.RandomState(1234)
rng.randn(100)

image.png

Numpy 统计分析

排序

  • 直接排序: numpy.sort()函数和numpy.ndarry.sort()函数
arr.sort(a, axis=-1, kind=‘quicksort’, order=None)
#a表示排序数组
#axis表示轴向,数组的维度(轴)是有索引号的,从0开始编号。
#对于二维数组,axis=0表示沿纵轴排序,axis=1表示沿着横轴排序;axis=-1表示沿着最后一维排
#kind= ′ quicksort ′ 快排;kind=′ 混排;kind=′ heapsort ′ 堆排;
#order:一个字符串或列表,可以设置按照某个属性进行排序
import numpy as np
dt = [('Name', 'S10'), ('Height', float), ('Age', int)]
values = [('Li', 1.8, 41), ('Wang', 1.9, 38),('Duan', 1.7, 38)]
a = np.array(values, dtype=dt)
print(a)
a=np.sort(a,order='Height') # 按照属性Height进行排序,此时参数为字符串
#a.sort(order='Height') 与上面语句等价
print(a)
#print(np.sort(a,order='Height'))
#array([('Duan', 1.7, 38), ('Li', 1.8, 41),('Wang', 1.9, 38)],dtype=[('Name', '|S10'), ('Height', '<f8'), ('Age', '<i4')])
a.sort(order=['Age', 'Height'])
print(a)
# 先按照属性Age排序,如果Age相等,再按照Height排序,此时参数为列表
#array([('Duan', 1.7, 38), ('Wang', 1.9, 38),('Li', 1.8, 41)],dtype=[('Name', '|S10'), ('Height', '<f8'), ('Age', '<i4')])
[(b'Li', 1.8, 41) (b'Wang', 1.9, 38) (b'Duan', 1.7, 38)]
[(b'Duan', 1.7, 38) (b'Li', 1.8, 41) (b'Wang', 1.9, 38)]
[(b'Duan', 1.7, 38) (b'Wang', 1.9, 38) (b'Li', 1.8, 41)]
  • 间接排序:argsort函数返回重新排序后数值的索引
arr.argsort(a,axis=-1, kind=‘quicksort’, order=None),

lexsort函数返回按照最后一个传入数据确定的排序顺序(相当于对多键值指定了 sort 函数的 kind 参数)

np.lexsort(a)
a=np.array([3,2,6,4,5])
b=np.array([50,30,40,20,10])
c=np.array([400,300,600,100,200])
d=np.lexsort((a,b,c)) #lexsort函数只接收一个参数,即(a,b,c)
print('排序后的数组为:\n',list(zip(a[d],b[d],c[d])))
#多个键值排序时按照最后一个传入数据确定排序顺序

去重和重复数据

去重:unique函数可以找出数组中的唯一值并返回排序后的结果

np.unique(ar, return_index=False, return_inverse=False,
return_counts=False, axis=None)

ar 接收要去重的数组。对数组去重后,会把数组元素从小到大排列。

#例4-2. 数组元素去重
arr = np.random.randint(1,10,size = 12) #生成随机数
print('创建的数组为:',arr)
print('去重后的数组为:',np.unique(arr))#去重并排序
arr=arr.reshape(3,4)
print('改变形状后的数组为:\n',arr)
print('改变形状后的数组去重后为:',np.unique(arr))

重复数据:

  • tile函数可以重复数据
np.tile(A,reps),其中A指定重复的数组,reps指定重复的次数。
  • Repeat函数可以重复数据
numpy.repeat(a,repeats, axis=None),

其中 a 是需要重复的数组元素,repeats 是重复次数,axis 指定沿着哪个轴进行重复,
axis= 0 表示按行进行元素重复;axis= 1 表示按列进行元素重复。

  • tile 函数是对数组进行重复操作,repeat 函数是对数组中的每个元素进行重复操作
    88.jpg
    55.jpg

描述性统计

  • 和——ndarray.sum(axis=None, dtype=None, out=None, keepdims=False)
  • 均值——ndarray.mean(axis=None, dtype=None, out=None, keepdims=False)
  • 标准差——ndarray.std(axis=None, dtype=None, out=None, ddof=0, keepdims=False)
  • 方差——ndarray.var(axis=None, dtype=None, out=None, ddof=0, keepdims=False)
  • 最小值——ndarray.min(axis=None, out=None, keepdims=False)(返回索引)
  • 最大值——ndarray.max(axis=None, out=None, keepdims=False)(返回索引)
  • 累计和——ndarray.cumsum(axis=None, dtype=None, out=None)
  • 累计积——ndarray.cumprod(axis=None, dtype=None, out=None)
  • 中位数——numpy.median(a, axis=None, out=None, overwrite_input=False, keepdims=False)
  • 极差——numpy.pad(array, pad_width, mode, **kwargs)
  • 协方差——numpy.cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None, aweights=None)

各函数中 axis 表示计算的范围,默认为 None,表示对全部元素进行计算。axis=1 表示沿横轴,axis=0 表示沿纵轴。

集合运算

image.png

Linear Algebra

点乘:

  • x.dot(y)
  • np.dot(x,y)
  • x@y

矩阵分解(逆矩阵和矩阵的值)
image.png

高级用法

生成模拟数据集

使用 NumPy 的随机函数、等差数组生成函数,生成需要的数据。由于生成的函数通常是一维数组,所以还需要进行数组的拼接:横向拼接实现多个特征(包括类标签)的组合;纵向拼接实现多个类别的组合。

借助行列拼接生成分类数据集

#在二维平面内创建不同位置为中心,产生正态分布的样本点
import os#导入os
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
path='D:/my_python/ch5/data/'
#如果path不存在,则创建它,包括一个或多个文件夹
if not os.path.exists(path):
os.makedirs(path)
#调用随机函数产生数据集
#在x,y平面内随机生成两类各num个正态分布的点,并分别添加类标签,形成数据集X
num=100#100个样本点
#生成类c0,类标签为0
c0_x0,c0_y0=0,0#设置类c0样本中心
c0_x=c0_x0+np.random.randn(num,1)#num行1列
c0_y=c0_y0+np.random.randn(num,1)#num行1列
c0_labels=0*np.ones((num,1))#num行1列,值全为0

#借助拼接函数对数据进行拼接

#横向拼接,将数据和类标签合并为一个num*3的数组
c0=np.hstack((c0_x,c0_y,c0_labels))
#生成类c1,类标签为1
c1_x0,c1_y0=6,1#设置类c1样本中心
c1_x=c1_x0+np.random.randn(num,1)#num行1列
c1_y=c1_y0+np.random.randn(num,1)#num行1列
c1_labels=1*np.ones((num,1))#num行1列,值全为1
#横向拼接,将数据和类标签合并为一个num*3的数组
c1=np.hstack((c1_x,c1_y,c1_labels))
#生成类c2,类标签为2
c2_x0,c2_y0=1,7#设置类c2样本中心
c2_x=c2_x0+np.random.randn(num,1)#num行1列
c2_y=c2_y0+np.random.randn(num,1)#num行1列
c2_labels=2*np.ones((num,1))#num行1列,值全为1
#横向拼接,将数据和类标签合并为一个num*3的数组
c2=np.hstack((c2_x,c2_y,c2_labels))

#纵向拼接合并数据集
#将c0,c1,c2三类数据纵向拼接合并为一个数据集X
X=np.vstack((c0,c1,c2))

#可视化

#绘制原始数据散点图,以*表示
p = plt.figure(figsize=(12,8))
plt.rc('font', size=14)#设置图中字号大小
plt.rcParams['font.sans-serif'] = 'SimHei'#设置字体为SimHei显示中文
plt.rcParams['axes.unicode_minus']=False#坐标轴刻度显示负号
# 子图1
ax1 = p.add_subplot(2,2,1)
plt.scatter(X[:, 0], X[:, 1], c=X[:,2])
plt.axis('tight')#修改x、y坐标的范围让所有的数据显示出来
plt.title('生成的数据样本')#添加标题
#将X转换为DataFrame对象,保存为.csv格式文件
pd.DataFrame(X).to_csv(path+'points_3classes.csv',sep = ',',index = False)
#读取数据文件,并转换为数组
X1 = pd.read_csv(path+'points_3classes.csv',sep = ',',encoding = 'utf-8').values
#子图2,可视化X1,与X对比
ax1 = p.add_subplot(2,2,2)
plt.scatter(X[:, 0], X[:, 1], c=X[:,2])#使用类标签设置点的颜色
#修改x、y坐标的范围让所有的数据显示出来
plt.axis('tight')
plt.title('从数据文件读取的数据样本')#添加标题
plt.show()

借助np.c[]生成线性回归样本集。

#例5-3,生成多元线性回归数据集

X1=np.random.uniform(0,10,num)#在0-10之间生成num个均匀分布的数
X2=np.random.uniform(0,10,num)
X3=np.random.uniform(0,10,num)
noise=np.random.randn(num)#生成正态分布的噪声
a1,a2,a3,b=-5,3,6,-8
Y=noise+a1*X1+a2*X2+a3*X3+b#线性方程叠加噪声
print('X1,X2,X3,噪声Y的形状分别为:',X1.shape,X2.shape,X3.shape,Y.shape)
#将X1,X2,X3,Y展平,相同位置的值配对为一个四维坐标系的点

Z=np.c_[X1.ravel(),X2.ravel(),X3.ravel(),Y.ravel()]
print('对齐后数据集Z的形状为:',Z.shape)
print('Z的前5行数据为:\n', Z[0:5,:])
#将Z转换为DataFrame对象,保存为.csv格式文件

#为每列设置名称,即特征名称
df_Z=pd.DataFrame({'X1':Z[:,0],'X2':Z[:,1],'X3':Z[:,2],'Y':Z[:,3]})
df_Z.to_csv(path+'3x_regression.csv',sep = ',',index = False)
#读取数据文件,并转换为数组
X = pd.read_csv(path+'3x_regression.csv',sep = ',',encoding = 'utf-8')
print('读取的数据集X的形状为:',X.shape)
print('读取的数据集X前5行数据为:\n', X.head())#第一行为列名称

Expressing Conditional Logic as Array Operations

相比于普通的条件循环,NumPy 能够依据其自身特点大大加快运算速度,因此我们有必要使用 NumPy 的表达来代替平时的条件逻辑。

import numpy as np
# transposing and swaping
# 置换和交换
arr1 = np.arange(16).reshape(4, 4)
arr2 = np.arange(16,32).reshape(4, 4)
con=np.array([True,True,False,False])
print("="*40)
print(arr1)
print("="*40)
print(arr2)
print("="*40)
print([(x if con1 else y)
for x,y,con1 in zip(arr1,arr2,con) ])
print("="*40)
print(np.where(con,arr1,arr2))