学习numpy快速入门教程 心得体会(3)

一、形状操作

1.改变数组的形状

注意:下列的命令是返回一个修改过后的数组,但并不会修改原数组

import numpy as np
def f(x, y):
    return 5*x+y
a = np.fromfunction(f,(3, 4), dtype=int)  #先创建一个新数组
print(a)
print(a.ravel())        #将数组中元素排成一列输出
print(a.reshape(2, 6))  #将数组的形状重塑,不改变原数组
print(a.T)              #将矩阵数组转置
print(a)                #再次打印原数组,验证其并未被改变


#输出:
[[ 0  1  2  3]
 [ 5  6  7  8]
 [10 11 12 13]]
[ 0  1  2  3  5  6  7  8 10 11 12 13]
[[ 0  1  2  3  5  6]
 [ 7  8 10 11 12 13]]
[[ 0  5 10]
 [ 1  6 11]
 [ 2  7 12]
 [ 3  8 13]]
[[ 0  1  2  3]
 [ 5  6  7  8]
 [10 11 12 13]]

这里辨析一下reshape函数与resize函数:前者是返回修改后的数组,并不会改变原数组的大小;而后者是直接改变了原数组的大小。

print(a.reshape(2, 6))  #将数组的形状重塑
print(a)                #验证原数组未被改变
a.resize(4, 3)          #直接改变原数组的大小
print(a)                #验证原数组已被改变


#输出:
[[ 0  1  2  3  5  6]
 [ 7  8 10 11 12 13]]
[[ 0  1  2  3]
 [ 5  6  7  8]
 [10 11 12 13]]
[[ 0  1  2]
 [ 3  5  6]
 [ 7  8 10]
 [11 12 13]]

2.数组矩阵的堆叠

堆叠的方式大致分为行堆叠vstack()和列堆叠hstack()两种,个人理解为拼接方式的不同。

另外,column_stack()函数比较特殊,对于二维数组的堆叠,其功能类似于hstack()函数,但对于一维数组的堆叠,会将一维转为二维且其功能与hstack()完全不同了,具体见下方代码示例:

import numpy as np
a = np.array([[4, 8], [2, 3]])
b = np.array([[1, 9], [5, 7]])
print(np.vstack((a, b)))  #将a,b数组行堆叠(上下拼接)
print(np.hstack((a, b)))  #将a,b数组列堆叠(左右拼接)
print(np.column_stack((a, b)))  #将a,b数组列堆叠,对于二维数组的堆叠类似hstack函数
c = np.array([4, 2])
d = np.array([5, 7])
print(np.vstack((c, d)))  #行堆叠
print(np.hstack((c, d)))  #注意这里堆叠后仍是一维数组
print(np.column_stack((c, d))) #将c,d一维数组转置后列堆叠且一维变二维


#输出:
[[4 8]
 [2 3]
 [1 9]
 [5 7]]
[[4 8 1 9]
 [2 3 5 7]]
[[4 8 1 9]
 [2 3 5 7]]
[[4 2]
 [5 7]]
[4 2 5 7]
[[4 5]
 [2 7]]

注意一点:hstack()对于一维数组堆叠后仍为一维数组(不仔细看,很容易以为变成二维)

3.将一个数组拆分成几个较小的数组

运用hsplit函数,可以将数组沿水平轴方向切割成几个较小的数组,方法是指定要返回的形状相等的数组的数量,或者指定应该在其之后进行分割的列。具体见下方代码示例:

import numpy as np
a = np.floor(10*np.random.random((2, 12)))
print(a)
print(np.hsplit(a, 3))  #将a数组分成大小相等的三块数组
print(np.hsplit(a, (3, 5))) #以第四列到第五列为切割线,分隔a数组


#输出:
[[5. 2. 3. 7. 5. 9. 7. 1. 8. 2. 0. 7.]
 [2. 6. 3. 4. 2. 5. 6. 9. 3. 3. 5. 4.]]
[array([[5., 2., 3., 7.],
       [2., 6., 3., 4.]]), array([[5., 9., 7., 1.],
       [2., 5., 6., 9.]]), array([[8., 2., 0., 7.],
       [3., 3., 5., 4.]])]
[array([[5., 2., 3.],
       [2., 6., 3.]]), array([[7., 5.],
       [4., 2.]]), array([[9., 7., 1., 8., 2., 0., 7.],
       [5., 6., 9., 3., 3., 5., 4.]])]

另外,除了hsplit(),还有vsplit():沿垂直轴切割,方法类似。

二、拷贝与视图

1.完全不复制

import numpy as np
a = np.arange(12)
b = a             #最简单的“完全不复制”的复制
print(b is a)     #验证b与a实质上指向同一个数组
b.shape = (3, 4)  #改变b的大小
print(a.shape)    #验证b的改变会影响到a
print(a)


#输出:
True
(3, 4)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

我的理解是b就是数组a的别名(类似C语言中的引用)改变b数组的大小或者元素都会影响到a数组

2.视图(浅拷贝)

import numpy as np
a = np.arange(12).reshape(3, 4)
c = a.view()   #创建一个a的视图
print(c is a)  #验证c与a指向的对象是不同
c.shape = (2, 6)
print(a.shape) #验证改变c的大小不会影响数组a的大小
c[0, 4] = 1234
print(a)       #验证改变c中元素会影响数组a中的元素


#输出:
False
(3, 4)
[[   0    1    2    3]
 [1234    5    6    7]
 [   8    9   10   11]]

对于视图,我的理解是改变视图的大小不会影响到原数组的大小,但改变视图中的具体元素则会影响到原数组中的元素。

3.深拷贝

这个很好理解,copy()函数可以生成原数组的副本,且两者完全不相关联,互不干扰。

import numpy as np
a = np.arange(12).reshape(3, 4)
d = a.copy()
print(d is a)
d.shape = (2, 6)
print(a.shape)
d[0, 0] = 999
print(a) 


#输出:
False
(3, 4)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

有时,如果不再需要原始数组,则可在切片后调用 copy。例如,假设a是一个巨大的中间结果(需要将其删除释放),最终结果b只包含a的一小部分,那么在用切片构造b时应该做一个深拷贝:

import numpy as np
a = np.arange(int(1e8))  #巨大的中间结果a
b = a[:100].copy()       #最终结果只取其中一部分,可用copy()
del a                    #这样删除a就无法影响到b

你可能感兴趣的:(numpy,学习,python)