今天继续来学习Numpy
ndarray内部的数据应该有什么样的规律呢?٩(๑>◡<๑)۶
还是先import numpy
input:
import numpy as np
对于ndarray结构来说,里面所有的元素必须是同一个数据类型的,如果不是的话,会自动的向下进行转换
input:
mix_list = [1,2,3,4,'5.1'] # 构造一个list结构
array = np.array(mix_list) # 将list结构转化为ndarray结构
print(array) # 打印array
output:
[‘1’ ‘2’ ‘3’ ‘4’ ‘5.1’]
可以看到,mix_list中’5.1’是一个字符串类型,其他的element都是整型;在转换成ndarray后,数组内的所有element都变成了字符串类型
ndarray基本属性操作
input:
print(type(array)) # 打印当前的变量属于什么数据类型
output:
<class 'numpy.ndarray'>
input:
array.dtype # 输出array数组中enement的数据类型
output:
dtype('<U21')
input:
array.itemsize #输出array数组中每个element的大小,以字节为单位
84
input:
array.shape #数组的维度,对于矩阵,n行m列
output:
(5,)
input:
array.size # 数组元素的总个数,相当于.shape中的 n * m的值
output:
5
input:
np.size(array) # 与array.size的输出相同
output:
5
input:
np.shape(array) #与array.shape的输出相同
output:
(5,)
input:
array.ndim # 秩,即轴的数量或维度的数量
output:
1
input:
array_two = np.array([1, 2, 3, 4, 5])
print(array_two)
output:
[1 2 3 4 5]
input:
# 对数组进行填充
array_two.fill(0)
array_two
output:
array([0, 0, 0, 0, 0])
索引与切片:
ndarray的索引与Python的索引规则相同,都是从0开始
input:
index_list = [1,2,3,4,5,6]
index_array = np.array(index_list)
index_array[0]
output:
1
ndarray切片操作的规则与Python也相同,都是左闭右开
- 如何理解左闭右开呢?
比如我们想要取从a到b的切片,那么在代码中就可以写成[a, b+1],索引为a的元素可以读到,但是无法读到b+1,最多读取到索引为b的元素
input:
index_array[1:3] # index_array = [1 2 3 4 5 6]
output:
array([2, 3])
":"后面什么都不写表示取到最后一个元素,“-3”表示从倒数第一个元素向前查3个元素
因此index_array[-3:]就表示从[1 2 3 4 5 6]中倒数第三个元素开始,取到最后一个元素
input:
index_array[-3:]
output:
array([4, 5, 6])
数组格式(多维的形式)
input:
array_2d = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
array_2d # 二维的3*3数组
output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
input:
array_2d.shape # 三行三列
output:
(3, 3)
input:
array_2d.size # 共9个元素
output:
9
input:
array_2d.ndim # 共2个维度
output:
2
input:
array_2d[1, 1] # 利用索引取第2行第2列
output:
5
input:
array_2d[1,1] = 10 # 利用索引修改数组元素的值
array_2d
output:
array([[ 1, 2, 3],
[ 4, 10, 6],
[ 7, 8, 9]])
input:
array_2d[1] # 利用第一个维度的索引,取出第二行所有的值
output:
array([ 4, 10, 6])
input:
array_2d[:,1] # “:”两边什么都不写说明取所有,此处表示第一个维度的每一个值都要渠道,而后面的1表示取第二个维度第二个值,结果就是取整个数组的第二列
output:
array([ 2, 10, 8])
input:
array_2d[0,0:2] # 利用索引加切片取值
output:
array([1, 2])
input:
array_2d
output:
array([[ 1, 2, 3],
[ 4, 10, 6],
[ 7, 8, 9]])
不同的复制操作
- 用等号复制
input:
original_array = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
original_array
output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
input:
copy01_array = original_array
copy01_array
output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
input:
copy01_array[1,1] = 100
copy01_array
output:
array([[ 1, 2, 3],
[ 4, 100, 6],
[ 7, 8, 9]])
input:
original_array
output:
array([[ 1, 2, 3],
[ 4, 100, 6],
[ 7, 8, 9]])
首先定义了一个original_array,接着用等号赋值给了copy01_array,然后修改copy01_array第二行第二列元素的值,最后发现original_array与copy01_array的值全都被修改了,这说明这两个数组使用的是同一块内存空间
- 用copy()方法复制
input:
original_array = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
original_array
output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
input:
copy02_array = original_array.copy()
copy02_array
output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
input:
copy02_array[1,1] = 10000
copy02_array
output:
array([[ 1, 2, 3],
[ 4, 10000, 6],
[ 7, 8, 9]])
input:
original_array
output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
可以看出,使用copy()方法复制之后,修改copy02_array对original_array是没有影响的,可以说明这两个数组使用的不是同一个内存空间
利用boolean类型作为索引
input:
array_data = np.arange(0,100,10) # np.arrange(a, b, c)的作用就是在a到b的区间内,平均生成10个数存放到数组array_data中
array_data
output:
array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
input:
mask = np.array([0,0,0,0,0,0,1,1,1,1],dtype=bool) # 我们可以假设array_data中的数据是考试分数,60分及以上是及格,0代表False,1代表True
print(mask) # 这样我们就得到了与array_data相同元素个数的索引
output:
[False False False False False False True True True True]
input:
array_data[mask] # 将索引传入array_data,就可以得到60及以上的分数
output:
array([60, 70, 80, 90])
input:
random_array = np.random.rand(10) # 这里是取10个随机数操作,暂时先用一下,以后还会再详细说一下
random_array
output:
array([0.40770108, 0.69797953, 0.59972498, 0.4589898 , 0.08336096,
0.48510752, 0.7527065 , 0.10379869, 0.15378716, 0.90431385])
input:
mask = random_array > 0.5 # random_array中大于0.5的元素为True,小于0.5的元素为False,将结果存入mask中
mask
output:
array([False, True, True, False, False, False, True, False, False,
True])
input:
array_data[mask] # 将mask传入上一个表示分数的array_data中,只会打印出array_data中以mask中与元素为True的索引的元素
output:
array([10, 20, 60, 90])
input:
array_where = np.array([10, 20, 30, 40, 50])
array_where > 30
output:
array([False, False, False, True, True])
input:
np.where(array_where > 30) # np.where()的作用是输出符合括号内条件元素的索引
output:
(array([3, 4]),)
input:
array_where[np.where(array_where > 30)] # 把np.where()输出的索引输入到array_where中,得到大于30的元素值
output:
array([40, 50])
修改ndarray中元素的数据类型
input:
array_float = np.array([1,2,3,4,5], dtype=np.float32) # 第一种,利用dtype来指定数组内元素的数据类型
array_float
output:
array([1., 2., 3., 4., 5.], dtype=float32)
input:
array_float.dtype # 数组.dtype输出数组内元素的数据类型
output:
dtype('float32')
input:
array_float.nbytes # 只输出数组内元素的占用空间,并不是数组+数组内元素的占用空间
output:
20
input:
array_object = np.array([1,10,3.5,'str'],dtype = np.object)
array_object
output:
array([1, 10, 3.5, 'str'], dtype=object)
input:
array_object * 2
output:
array([2, 20, 7.0, 'strstr'], dtype=object)
input:
array_int = np.array([1,2,3,4,5]) # 第二种转换数据类型的方式
np.asarray(array_int, dtype = np.float32)
output:
array([1., 2., 3., 4., 5.], dtype=float32)
input:
array_int #利用np.asarray()转换完之后并不改变原有的数据类型
output:
array([1, 2, 3, 4, 5])
input:
array_float2 = np.asarray(array_int, dtype = np.float32) # 因此使用np.asarray()修改数据类型时,需要另外一个变量来接收
array_float2
output:
array([1., 2., 3., 4., 5.], dtype=float32)
input:
array_int # 可以看到array_int不变
output:
array([1, 2, 3, 4, 5])
input:
array_int.astype(np.float32) # 第三种转换数据类型的方式
output:
array([1., 2., 3., 4., 5.], dtype=float32)
input:
array_int
output:
array([1, 2, 3, 4, 5])
2020年7月23日更新