NumPy数组基础


数组与向量化计算。优点:数组类型;快速的向量化计算(由于由C语言实现)
导入:

import numpy as np  # 标准的NumPy导入方式

比较NumPy的数组与list的效率,因为NumPy用C语言实现。并且矩阵运算不需要循环。

# 100万个数循环10次*2,计时
arr = np.arange(1000000)
ls = list(range(1000000))
%time for _ in range(10):arr2 = arr*2             # Wall time: 22.9 ms
%time for _ in range(10):ls2 = [x*2 for x in ls]  # Wall time: 750 ms

数据结构-ndarray:多维数组对象

数组内数据同类型,默认float型
属性:
.shape: 各维度大小
.dtype: 数据类型
.ndim: 几维

data = np.random.randn(2,3)  # 生成2*3的二维随机数组
data
# array([[-0.00513612, -0.13435869,  0.41686502],
#        [-0.09536552, -0.65670825,  1.03684946]])
?np.random.randn(d0, d1, ..., dn) # 返回服从标准正态分布的样本
# 参数是各维度大小,参数为空时返回一个符合的实数
  1. 生成一维数组:从任意序列使用np.array(seq) 转换为一维数组
l = [1,2,3]
arr = np.array(l)   # 列表转换为数组
arr.ndim  # 1
arr.dtype  # int32

或使用arange():range()的数组版,将range结果变成数组

np.arange(5)  # array([0, 1, 2, 3, 4])
np.arange(2,8,2)  # 从2到7,步长是2,array([2, 4, 6])
  1. 生成多维数组,从嵌套序列转换,几重嵌套就是几维
l = [[1,2,3],[4,5,6]]
arr = np.array(l)
arr.shape            # (2, 3)

np.array(seq): 默认复制所有的数据
np.asarray(seq): 也是将序列转换为数组,但如果输入已经是ndarray,则不再复制
3. 生成特殊数组

np.zeros(5)        # 生成全0数组,1*5,默认float型,array([0., 0., 0., 0., 0.])
np.ones((2,3))     # 生成全1数组,2*3,参数用元组给出
np.empty((2,3,2))  # 生成未初始化值的数组,不一定是0,可能是内存原来的垃圾值
np.identity(3)     # 生成3*3的对角矩阵,对角线全是1,等价于
np.eye(3)
其余生成函数 描述(_like:就是与给定数组形状一样)
ones_like 根据所给数组生成形状一样的全1数组
zeros_like 同上,全0
empty_like 同上,全未初始化
full 根据给定形状和数据类型生成指定数值的数组
full_like 根据给定数组生成形状一样但是内容是指定数值的数组

数据类型dtype

全名:np.类型名+元素位数:np.int8/16/32/64,np.float16/32/64/128,np.complex64/128/256,np.bool,np.string_,np.unicode
简名:int,float,complex,bool(非0都是True),str
用场:

  1. 转换为数组时或生成数组时同时指定类型,通过参数dtype=
    np.array(seq,dtype=)
    np.empty(n,dtype=)
  2. 显式改变类型:reresult = .astype(类型名) 总是返回一个新数组
    前提:类型之间要能转换,浮点数转为整数则丢失小数部分
    arr2 = arr.astype(float) 等价于 arr2 = arr.astype(np.float64)

数组算术-向量化

等尺寸数组之间的算术操作是逐元素操作。
*:逐元素相乘
/:逐元素相除
**n:逐元素计算n次幂
<等大小比较:逐元素比较大小,返回同等大小的True/False数组
不同尺寸的数组间操作,将用到广播特性。

索引与切片

1.一维数组直接索引与切片,同列表一样。
注意,对切片赋值时,是赋给切片内所有的数据。

arr = np.arange(5)
arr[2:5] = 10
arr   # [ 0,  1, 10, 10, 10]

注意2:数组的切片类似于原数组的引用(指针),任何对切片的操作都将反映到原数组上。原因是NumPy设计为处理非常大的数组,不能动不动就复制数组。如果一定要复制数组切片,则必须显式的复制,如arr[5:8].copy()

arr = np.arange(5)
slice = arr[2:5]
print(slice)    # [2 3 4]
slice[:] = 10   # 引用数组的所有值
print(slice)    # [10 10 10]
print(arr)      # [ 0,  1, 10, 10, 10]

2.高维数组的一个索引是低一维的数组
索引单个元素:可以每个中括号一个索引也可以通过索引值的列表
比如二维数组 arr[0][2] 等价于 arr[0,2],轴0是行,轴1是列。
数组子集选择中,返回的数组都是引用。
3. 数组切片
一维直接切
高维中,只有一组切片时是沿轴0切片,比如二维数组arr[:2]:选择前两行
多组切片也是逗号列表,比如arr[:2,1:]表示前两行第2列到最后一列。
多组切片维度不变,但索引与切片混合时,得到维度减少的结果。

arr = np.eye(3)
arr[1:2,:2]    # array([[0., 1.]]),.ndim=2  ,两组切片
arr[1,:2]      # array([0., 1.]),.ndim=1  ,索引与切片混合

对切片表达式赋值时,整个切片所有数据都被赋值

arr = np.eye(3)
arr[:,1:] = (6,3)   # 所有行,  # arr[:,1:] = 6,则后两列全为6
print(arr)

在这里插入图片描述

  • 布尔索引:使用逻辑表达式作为索引
    比如data[(data<0) & (data>-3)] = 0
    与或非必须使用逻辑运算符&,|,!(~条件),不能使用and,or
  • 神奇索引:使用整数数组进行索引,见《数据分析》P103

数组转置与换轴

.T属性返回转置后的数组
.reshape(各维度大小的元组,order=‘C’):改变数组形状,默认按行排列,‘F’按列排列

arr = np.arange(6).reshape((2,3))  # 变成2*3
print(arr)
print(arr.T)   # .T属性转置

在这里插入图片描述
计算矩阵内积,即矩阵乘法

arr = np.random.randn(3,2)
print(arr)
np.dot(arr.T,arr)  # 3*2 2*3 = 2*2

在这里插入图片描述
转置是换轴的一个特例,轴0(行)与轴1(列)互换,因为二维数组换轴就是转置。换轴只针对高维数组而言,
法一:a.swapaxes(axis1, axis2) : Return a view of the array with axis1 and axis2 interchanged.返回的是数据的视图,没有复制数据
法二:a.transpose(新的所有轴编号的元组)

# 换轴,对于3维数组,轴0是最外层,轴1是行,轴2是列
arr = np.arange(6).reshape((1,3,2),order='C') 
print(arr)
print(arr.swapaxes(1,2))  # 轴1与轴2互换,等价于下面
print(arr.transpose((0,2,1)))

在这里插入图片描述

通用函数ufunc

逐元素数组函数

arr = np.arange(5)
print(np.sqrt(arr))   # 根号
print(np.exp(arr))    # 指数

x = np.random.randn(3)
y = np.random.randn(3)
print('x:',x,'\ny:',y)
print('max:',np.maximum(x,y))   # 计算每个位置的元素最大值
decimals,integer = np.modf(x)  # 返回每个元素的小数部分和整数部分,各为一个数组
print('小数:',decimals,'整数:',integer)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
示例:根据网格数据计算 x 2 + y 2 \sqrt{x^2+y^2}

points = np.arange(-5,5,0.01) # 1000个相同步长的点
xs, ys = np.meshgrid(points,points)  # 接受两个一维数组,根据两个数组的所有(x,y)对生成一个二维矩阵
print('xs:',xs)
z = np.sqrt(xs ** 2 + ys ** 2)
print('z:',z)

# 二维数组可视化
import matplotlib.pyplot as plt
plt.imshow(z,cmap='summer');plt.colorbar()  # 在图旁边把colorbar显示出来
plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")  # 添加标题,公式用LaTeX表示

在这里插入图片描述
注:matplotlib.pyplot.imshow(X, cmap=None)
X: 要绘制的图像或数组。
cmap: 颜色图谱(colormap), 默认绘制为RGB(A)颜色空间。例如;matplotlib.pyplot.imshow(img, cmap=‘jet’)

颜色图谱的取值:

数组中的条件判断np.where

典型用场:根据一个数组,根据条件改变里面的值,变成另一个数组
np.where(condition, x, y): Return elements chosen from x or y depending on condition.
返回值 : An array with elements from x where condition is True, and elements from y elsewhere.

# 将矩阵中的正值替换为2,负值不替换
arr = np.random.randn(4,4)
np.where(arr > 0,2,arr)  # 应该是逐元素判断条件并应用

在这里插入图片描述

统计函数

axis问题:二维数据拥有两个轴:轴0看做行,轴1看做列。
但轴向不等于轴,0轴向:沿着行的方向即垂直往下,1轴向:沿着列的方向即水平延伸。
在这里插入图片描述
统计函数里的参数axis表示沿轴向计算(along)

arr = np.random.randn(2,3)
print(arr)
print(arr.mean(axis=1))  # 跨列计算,即行均值
print(arr.sum(axis=0))   # 跨行计算,即列和

常用数组统计方法:
在这里插入图片描述
True/False数组
计数:.sum():计算True的个数

arr = np.random.randn(100)
(arr > 0).sum()     # 56

.any(): 是否至少有一个True
.all(): 是否全为True
非布尔值数组也适用,非0均为True。

排序
.sort([axis]): 直接改变原数组,默认升序,可选参数axis表示按轴向
例如二维数组中 arr.sort(axis=1) :按列的方向,即对每一行排序。
np.sort(arr): 返回排好序的数组拷贝

集合操作:针对一维数组1d
np.unique(arr): 求arr中的唯一值(不重复的值),并排序,等价于sorted(set(arr))

arr = np.array(['a','b','b'])
print(np.unique(arr))  # ['a' 'b']
sorted(set(arr))       # ['a', 'b']

np.in1d(arr1,arr2): arr1中的值是否包含在arr2中,类似于R的%in%,返回同等大小的True/False数组。

其他集合操作 描述
intersect1d(x,y) 求交集,并排序
union1d(x,y) 求并集,并排序
setdiff1d(x,y) 求差集,在x中但不在y中的x元素
setxor1d(x,y) 求异或集,在x或y中,但不属于交集的元素

数据在硬盘上的存取

np.save(路径,arr): 将数组保存到硬盘,默认未压缩,后缀.npy
np.load(路径) :将数组载入
详情见P116

线性代数

NumPy中矩阵*矩阵是逐元素相乘,因此dot()方法用于矩阵乘法。
x.dot(y) \Leftrightarrow np.dot(x,y) \Leftrightarrow x @ y:
如果是两个向量,则返回其内积(一个数);如果是两个矩阵,则返回矩阵的乘积。

x = np.array([[1,2,3],[4,5,6]])
y = np.array([[6,23],[-1,7],[8,9]])
x @ y

numpy.linalg拥有一个矩阵分解的标准函数集及矩阵常用函数
使用:np.linalg.inv(arr)
from numpy.linalg import inv,qr
在这里插入图片描述

伪随机数生成numpy.random模块

比Python内建的random模块快了一个数量级
伪随机数:根据算法由随机数生成器中的随机数种子生成的。
更改NumPy中的随机数种子:np.random.seed(1234):使得随机数据可预测。
在这里插入图片描述
注:上下限的区间均是不包含右端点

示例:随机漫步

随机漫步,从0开始,步进只能为1或-1,二者发生概率相等,计算累积值。

nsteps = 1000  # 1000步
drows = np.random.randint(0,2,size=nsteps)  # 一次性生成1000个0,1
steps = np.where(drows == 0,-1,1)           # 把0全改为-1
walk = steps.cumsum()                       # 计算步进的累积值
print(walk.min(),walk.max())                # -25 15
plt.plot(walk[:100])                        # 画出前100步

在这里插入图片描述
何时第一次朝某个方向连续走了10步?

(np.abs(walk)>=10).argmax()-10     # 47
# 先得到走了超过10步的布尔数组,再计算第一个True的位置,
# 得到第一次走了10步的位置,-10得到何时开始走这10步
# argmax():返回最大值的第一个位置,在这里True就是最大值,效率不高,因为它首先要完整扫描整个数组
发布了24 篇原创文章 · 获赞 6 · 访问量 1180

猜你喜欢

转载自blog.csdn.net/wbing96/article/details/103221519