从Python转到Numpy (二)

numpy 的基本数据类型是ndarray(数组),ndarray在内存中的是一维连续存储,支持索引。换句话说,数组映射一个连续的内存块,可以使用索引值进行数据访问。索引依次由形状和数据类型定义。

# 创建一个0-9的数组,改为3行3列的二维数组,单个元素的数据类型为np.int16(2个字节)
z = np.arange(9).reshape(3,3).astype(np.int16)

print(z.itemsize) # 单个元素的字节数
2

print(z.shape) #  数组的形状
(3, 3)

print(Z.ndim) # 数组的维数
2
可以算出数组的stides步长,步长定义了遍历数组时每个维度中要跨步的字节数。
strides = z.shape[1]*z.itemsize, z.itemsize
print(strides)
(6, 2)

print(z.strides) 
# 第一个维度,也就是行方向上每行要跨出6(3*2)个字节
# 第二个维度,也就是列方向上每列要跨出2个字节
(6, 2)

数组元素布局

数组扁平化后元素布局

数组内存布局

当对数组使用索引取值时,返回的是原始数组的视图,比如

v = z[::2,::2] #两个维度上,每隔1个元素取值

数组元素布局

 

数组扁平化后元素布局

数组内存布局

区分视图和副本

首先要区分索引和花式索引,前者返回的是原始数组的视图,后者返回的是原始数据索引后的副本。修改前者的值会影响原始数组。

z = np.zeros(9)
z_view = z[:3]
z_view[...] = 1
print(z)
out:[ 1.  1.  1.  0.  0.  0.  0.  0.  0.]

z = np.zeros(9)
z_copy = z[[0,1,2]] # 花式索引
z_copy[...] = 1
print(z)
out:[ 0.  0.  0.  0.  0.  0.  0.  0.  0.]

如果不确定索引返回的是原始数组的视图还是副本,可以通过结果的base属性确认,如果base的值是None,则返回的结果是副本。

注意某些numpy函数返回的是视图,比如ravel,而flatten返回的是副本,虽然两者都得到扁平后的数据。

 

代码产生的临时副本

X = np.ones(10, dtype=np.int)
Y = np.ones(10, dtype=np.int)
A = 2*X + 2*Y

运行上边的代码,除了显式的产生了X,Y和A三个数组外,还隐式的生成了两个数组2*X和2*Y。当数组非常大的时候可能会产生性能问题。解决问题的办法是显示调用numpy函数中的out参数, 明确指定输出结果到已经声明的变量。

X = np.ones(10, dtype=np.int)
Y = np.ones(10, dtype=np.int)
np.multiply(X, 2, out=X)
np.multiply(Y, 2, out=Y)
np.add(X, Y, out=X)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值