【numpy】ndarray



2017年07月05日    Author:Guofei

文章归类: 0x12_Pandas与numpy    文章编号: 200

版权声明:本文作者是郭飞。转载随意,但需要标明原文链接,并通知本人
原文链接:https://www.guofei.site/2017/07/05/ndarray.html


生成

lst = [[1.0, -2], [-3, 4]]
x = np.array(lst, dtype=float)
# dtype=float, int, np.complex128

np.array(lst, ndmin=3)  # shape = (1, 2, 2)
y = array(lst, ndmin=4)  # shape = (1, 1, 2, 2)

np.zeros(shape=(5, 2), dtype=int)

# 含头不含尾:
np.arange(start=0, stop=11, step=1)
# 含头含尾:
np.linspace(start=0, stop=5, num=9)

np.eye # 对角矩阵

np.random.rand(2, 2, 2) # 2x2x2 的随机矩阵
# 占用 bytes
z.size * z.itemsize

取数

  • 切片取数:共享内存(对于多维数组,如果每一维都用切片,也共享内存)
    a[3:5]  # 含头不含尾
    a[:-1]  # -1表示最后,仍然不含尾
    a[2, 3] = 7, 8  # 切片用来改array
    b = a[2, 3]  # a和b共享内存空间
    a[1:-1:2]  # 最后一个数是步长
    a[::2]  # 省略表示头部
    
  • 用list取数:不共享内存(对于多维数组,可以用切片+list混用方式取数,只要有list就不共享内存)
    a=np.arange(1,10,1)
    b=a[[1,2,3]] # 修改b的元素值,不影响a
    
  • array取数:不共享内存
    a=np.arange(1,10,1)
    b=a[np.array([1,4,1])]
    
  • 布尔取数:不共享内存
    a=np.arange(0,5,1)
    b=a[np.array([True,False,True,False,True])]
    

一个实际案例:

a=numpy.random.rand(10)
a[a>0.5]

摊平操作

index 相关


# 6x7x8 矩阵的第 100 个元素,其 index 是什么
np.unravel_index(indices=100, shape=(6, 7, 8)) # 返回 (1, 5, 4)

# 6x7x8 矩阵,其坐标 (1, 5, 4) 的元素,是第几个元素
np.ravel_multi_index(multi_index=(1, 5, 4), dims=(6, 7, 8)) # 返回 100


# 以上方法也可以输入多组值,同时计算和返回
# 例如:
x_arr, y_arr = np.unravel_index(indices=[1, 2, 3], shape=(3, 3))
# 返回 (array([0, 0, 1]), array([1, 2, 0]))

# (0, 0) 和 (1, 2) 对应第几个?
np.ravel_multi_index(multi_index=[(0, 1), (0, 2)], dims=(3, 3))
# 返回 array([0, 5])

# 摊平
x.flatten()

# 取摊平后的第 6 个元素
x.item(6)

习题:有一个5x5的零矩阵,使随机n个元素变成1

x = np.zeros((5, 5))
n = 3
idx = np.random.choice(a=range(x.size), size=n, replace=False)
idx2 = np.unravel_index(indices=idx, shape=x.shape)
x[idx2] = 1

方法

a.shape

  • 返回a的维度
    • 如果a是一维数组,输出为(4,)
    • 二维数组,输出为(2, 1)
    • 如果某一维不规则,那么不显示这一维(2,) a.shape返回array的维度
      a.shape
      
  • 可以对a.shape赋值,效果是改变维度
    a=numpy.array([[1,2,3],[4,5,6]])
    a.shape=3,2
    
  • 在赋值时,用-1表示自动计算这一维的长度
    a=numpy.array([[1,2,3],[4,5,6]])
    a.shape=3,-1
    

reshape

  • reshape与shape的区别是,reshape保持原数组维度不变
  • 相同点是,内存是共享的
a=numpy.array([[1,2,3],[4,5,6]])
b=a.reshape((3,2))

这里生成的a和b维度不同,但是共享内存

比较而言,用shape,直接改了原array:

a=numpy.array([[1,2,3],[4,5,6]])
b=a
b.shape=3,-1
b.shape=6  # 变成一维的

这里a,b的维度都改了

dtype

a.dtype#返回元素类型
a=numpy.array([1,2,3,4],dtype=numpy.float)#指定元素类型
a=numpy.array([1,2,3,4],dtype=numpy.complex)#指定元素类型

显示可用的dtype列表

set(numpy.typeDict.values())

np.pad:四周添加数字

np.pad(array, pad_width, mode='constant')

  • pad_width: ((before_1, after_1), ... (before_N, after_N)),例如 ((2, 3), (4, 5)) 表示第1纬度前填充2后填充3,第2纬度前填充4后填充5
  • mode
    • ‘constant’ (default) 常量填充。默认填0,配合 constant_values=((-10, 10), (-20, 20)) 指定填充什么数字。上面是第1个纬度前后填充-10和10,第二个纬度前后填充-20,20
    • ‘edge’ 用边缘填充
    • 还有很多填充模式,用的时候查

where

x = np.array([1, 2, 0, 0, 3, 2, 0])
np.where(x != 0) # 返回符合条件的 index
np.where(x != 0, 9, 99) # 符合条件则填充为 9,否则填充为 99

统计方法

以下方法都可以

  1. 对数组操作。
  2. 加nan表示跳过nan,例如 nanmean
方法 说明
sum  
mean  
std,var  
min,max  
argmin,argmax 最小值和最大值的索引
cumsum  
cumprod  
diff  
sort 排序

使用详解

# 对 ndarray 的操作
arr1 = np.random.rand(5, 3)
np.mean(arr1)
np.mean(arr1, axis=1, keepdims=True)  
# 1. 对第axis维度求平均
# 2. keepdims 默认为 False,表示把结果变成一维的

# 加nan表示跳过nan
np.nanmean(arr1)

其它统计学方法

# 协方差矩阵
np.corrcoef(arr1)

常用方法

np.ceil
np.floor
np.rint
np.isnan



np.unique # 去重并排序


np.unique(
    arr
    , return_index=True  # 额外返回一个array,记录去重后的元素来自 arr 的哪个位置
    , return_inverse=True  # 额外返回一个array,用它+返回值可以重新构建 arr
    , return_counts=True  # 额外返回一个array,记录元素个数
    , axis=0  # 按照axis去重;如果没有,去重粒度是元素,
)

集合

np.intersect1d([1, 2, 3], [4, 3, 5])  # 交集
np.union1d([1, 5, 4], [5, 3, 1])  # 并集

np.in1d(ar1=[1, 4, 4, 1, 2], ar2=[1, 2])  # ar1 中每个元素,是否是 ar2 中的元素。返回一个 np.array<bool> ,大小与 ar1 一致

逻辑运算

np.logical_not([True, True, False])  # 求否
np.logical_or(arr1, arr2)
np.logical_and(arr1, arr2)

# 更好记:
arr1 & arr2
arr1 | arr2
~arr1

np.all
np.any


np.isnan(np.array([1, np.nan]))

sort

import numpy as np
a=np.random.randn(10,3)
a.sort(axis=1) # 直接改变a
np.sort(a) # 不改变a,而是返回一个排序完毕的ndarray
  • axis=1,axis=1是对行降序,axis=0是对列降序
  • 只能降序排列,向生序 a[:,::-1]
  • kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}

np.argsort

np.meshgrid

X, Y = np.meshgrid(np.arange(3), np.arange(4))

矩阵操作

常用方法

a=np.random.rand(3,4)
np.fliplr(a) # 左右翻转
np.flipud(a) # 上下翻转
np.rot90(a,k=3) # 逆时针转动k次

np.eye(N=4,M=3,k=2) # 生成一个对角阵,N*M大小,k是向右上角偏置量
np.diag(a,k=1) # 取出对角元素,放到一维数组中,返回一个 1darray
np.diag([1,2,3],k=2) # 生成对角矩阵(一维数组转二维数组)
# np.diag 没有 keepdim 这类入参,可以用 np.diag(np.diag(a)) 来提取对角矩阵

np.triu(m=a,1) # 矩阵的上三角部分
np.tril(m=a,1) # 矩阵的下三角部分
np.tri(N=3,M=4,k=1) # 生成一个下三角矩阵,元素是0和1

np.vander(x=[1,2,3],N=5) # 生成一个 Vandermonde matrix,每一行是x中的元素,N列

(a>0.5).any(axis=0) # 每列是否有True
(a>0.5).any(axis=1) # 每行是否有True


np.tile(np.array([[1, 2], [3, 4]]), (3, 2))
# 把一个矩阵复制 3*2 次,也就是行变成 3 倍,列变成 2 倍

矩阵拆拼

拼装

import numpy as np
a=np.random.rand(3,3)
b=np.random.rand(3,3)
np.concatenate([a,b],axis=0) # axis=0是竖着拼起来,axis=1是横着拼起来

scipy距离矩阵

https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cdist.html#scipy.spatial.distance.cdist

import numpy as np
from scipy import spatial

num_points = 8
points = range(num_points) # generate index of points
points_coordinate = np.random.rand(num_points, 2) # generate coordinate of points
distance_matrix = spatial.distance.cdist(points_coordinate, points_coordinate, metric='euclidean')

存文件和读文件

文本类型的存和读

# 以下两个方法可以读 csv/txt 等格式
arr1 = np.genfromtxt('file1.csv', delimiter=',')
# 如果某个数据是字符串,相应位置会读取为nan
arr2 = np.loadtxt('file1.csv', delimiter=',', skiprows=1)
# 多了一个 skiprows 方法,一般用来跳过第一行(字段名)
# 如果某个数据是字符串,会报错

二进制形式存和读(*.npy 格式)

# 存
np.save('file4.npy', arr1)

# 读
np.load('file4.npy')

多个变量批量存/读(*.npz 格式)

# 存
# 区别是:是否压缩
np.savez('file2.npz', arr1=arr1, arr2=arr2)
np.savez_compressed('file2_compressed', arr1=arr1, arr2=arr2)
# 如果不指定变量名,变量值默认为 arr_1, arr_2 等




# 读
npzfile = np.load('file2.npz')

npzfile.files  # 一个列表,都有哪些变量名
npzfile['arr2']  # arr2 这个变量的值
npzfile.get(key='arr3', default=1)  # 同上,但是对于不存在的变量,返回一个默认值

npzfile.items()  # 一个 iterator,key-value 结构
npzfile.values()  # 一个 iterator,存放value

scipy 也可以读写文件(据说与Matlab通用)

scipy.io.savemat('file2_scipy', {'arr1': arr1, 'arr2': arr2})

data_scipy = scipy.io.loadmat('file2_scipy')

其它

np.einsum 比较复杂,但是据说效率较低,暂时不写了


您的支持将鼓励我继续创作!