引用机制意味着,Python并没有为b分配新的空间来存储它的值,而是让b指向了a所分配的内存空间,因此,改变b会改变a的值:
a = np.array([0,1,2,3,4,5])
b = a[2:4]
# b = array([2, 3])
b[1] = 40
a
# a = [ 0 1 2 40 4 5]
而这种现象在列表中并不会出现:
a = [0,1,2,3,4,5]
b = a[1:3]
# b = [1, 2]
b[1] = 40
a
# a = [0, 1, 2, 3, 4, 5]
这样做的好处在于,对于很大的数组,不用大量复制多余的值,节约了空间。
缺点在于,可能出现改变一个值改变另一个值的情况。
a = np.array([0,1,2,3,4,5])
b = a[2:4].copy()
b[1] = 10
a
# a = array([0, 1, 2, 3, 4, 5])
与range函数类似,我们可以使用arange函数来产生等差数组。
a = np.arrage(0,100,10)
# a = array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
index = [1,3,5]
y = a[index]
# y = array([10, 30, 50])
mask = np.array([0,1,2,3,0,0,0,4,2,0],dtype = "bool")
# mask = array([False, True, True, True, False, False, False, True, True,False])
s = a[mask]
# s = array([10, 20, 30, 70, 80]),即将True的部分对应a的内容拿出来了
mask 必须是布尔数组,长度必须和数组长度相等。
对于二维花式索引,我们需要给定行和列的值:
在这里沿用之前的数组:
a = np.array([[0,1,2,3,4,5],[10,11,12,13,14,15],[20,21,22,23,24,25],[30,31,32,33,34,35],[40,41,42,43,44,45],[50,51,52,53,54,55]])
a
b = a[(0,1,2,3,4),(1,2,3,4,5)]
# b = array([ 1, 12, 23, 34, 45])
b = a[3:,(0,2,4)]
# b = array([[30, 32, 34],
# [40, 42, 44],
# [50, 52, 54]])
mask = np.array([1,0,1,0,0,1],dtype = bool)
a[mask,2]
# array([ 2, 22, 52])
与切片不同,花式索引返回的是原对象的一个复制而不是引用
a[:3]
# array([[ 0, 1, 2, 3, 4, 5],
# [10, 11, 12, 13, 14, 15],
# [20, 21, 22, 23, 24, 25]])
mask = np.array([0,1,1,0,0,1],dtype = bool)
a[mask]
# array([[10, 11, 12, 13, 14, 15],
# [20, 21, 22, 23, 24, 25],
# [50, 51, 52, 53, 54, 55]])
where(array)
where函数会返回所有非零元素的索引。
a = np.array([70,2,30,4,5])
a > 10
# array([ True, False, True, False, False])
np.where(a>10)
# (array([0, 2], dtype=int64),)
注意到where的返回值是一个元组。返回的是索引位置,索引[1,3]大于10的数
a[a>10]
# 或 a[np.where(a>10)]
# 所得结果均为 array([70, 30])
首先是最原始的转换方式:
a = np.array([1.2,6],dtype = float)
# a = array([1.2, 6. ])
a = np.array([1.2,6],dtype = float)
np.asarray(a,dtype = int)
a = np.array([1.2,6],dtype = float)
b = a.astype(int)
# b = array([1, 6])
astype方法返回一个新数组,不改变原数组的值
我们以豆瓣10部高分电影为例
# 电影名称
mv_name=['肖申克的救赎','控方证人','美丽人生','辛德勒名单','阿甘正传','霸王别姬','泰坦尼克号','这个杀手不太冷','教父','海上钢琴师']
# 评分人数
mv_num = np.array([1231413,1234221,231122,323423,2131231,232424,4564564,3242341,123123,123124])
# 评分
mv_score = np.array([9.5,9.8,9.2,9.3,9.5,9.3,9.5,9.3,9.7,9.9])
# 电影时长
mv_length = np.array([142,123,234,211,242,122,234,212,123,243])
np.sort(mv_num)
sss = np.argsort(mv_num)
通过这样做就能很好知道其他的相关信息:
mv_name[sss[0]]
# 例如这样就知道点评人数最少的电影名称
np.sum(mv_num)
# mv_num.sum()
np.max(mv_score)
# mv_score.max()
np.min(mv_score)
# mv_score.min()
np.std(mv_num)
# mv_num.std()
np.cov(mv_score,mv_length)
a = np.arange(6)
a.shape = 2,3
# array([[0, 1, 2],
#[3, 4, 5]])
a.shape
#(2, 3)
与之相对的方法是reshape,但它不会修改原来数组的值,而是返回一个新的数组
a.reshape(2,3)
#array([[0, 1, 2],
#[3, 4, 5]])
a = a.reshape(2,3)
# a = array([[0, 1, 2],
#[3, 4, 5]])
a.T # 或 a.transpose()
# array([[0, 3],
#[1, 4],
#[2, 5]])
有时我们需要将不同的数组按照一定的顺序连接起来:concatenate((a0,a1,…,aN),axis=0)
注意,这些数组要用()包括到一个元组中去。
除了给定的轴外,这些数组其他轴的长度必须是一样的。
x = np.array([[1,2,3,4],[5,6,7,8]])
y = np.array([[51,52,53,54],[65,66,67,68]])
默认沿着第一维进行连接:
z = np.concatenate((x,y))
# z = array([[ 1, 2, 3, 4],
#[ 5, 6, 7, 8],
#[51, 52, 53, 54],
#[65, 66, 67, 68]])
沿着第二维进行连接:
z = np.concatenate((x,y),axis = 1)
# z = array([[ 1, 2, 3, 4, 51, 52, 53, 54],
#[ 5, 6, 7, 8, 65, 66, 67, 68]])
注意到这里x和y的形状是一样的,还可以将它们连接成三维的数组,但是concatenate不能提供这样的功能,不过可以这样:
z = np.array((x,y))
# z = array([[[ 1, 2, 3, 4],
#[ 5, 6, 7, 8]],
#[[51, 52, 53, 54],
#[65, 66, 67, 68]]])
事实上,Numpy提供了分别对应这三种情况的函数:
np.vstack((x,y))
# z = array([[ 1, 2, 3, 4],
#[ 5, 6, 7, 8],
#[51, 52, 53, 54],
#[65, 66, 67, 68]])
np.hstack((x,y))
# z = array([[ 1, 2, 3, 4, 51, 52, 53, 54],
#[ 5, 6, 7, 8, 65, 66, 67, 68]])
np.dstack((x,y))
# z = array([[[ 1, 2, 3, 4],
#[ 5, 6, 7, 8]],
#[[51, 52, 53, 54],
#[65, 66, 67, 68]]])
a = np.array([-1,3,-4,5])
# a = array([-1, 3, -4, 5])
b = np.abs(a)
# b = array([1, 3, 4, 5])
b = np.exp(a)
# b = array([3.67879441e-01, 2.00855369e+01, 1.83156389e-02, 1.48413159e+02])
b = np.median(a)
# b = 1.0
b = np.cumsum(a)
# b = array([-1, 2, -2, 3], dtype=int32)