numpy小练习

numpy是python中的一个基础工具包,主要用于科学计算和数据分析。
在使用numpy这个工具包的时候,使用最多的当属于数组array这种数据存储结构了。

numpy中的数组结构

接下来开始介绍numpy中的数组array。
想使用一个数组来存储数据,首先要创建一个数组。创建数组非常容易,使用numpy内置的array函数就可以直接创建一个数组。
例如,创建一个包含0到9十个数字的数组。

import numpy as np
nparray = np.array([0,1,2,3,4,5,6,7,8,9])
print(nparray)
[0 1 2 3 4 5 6 7 8 9]

如果我们想查看一个数组的形状,可以使用数组的shape属性,shape属性的返回结果是一个元组,元组中的每一个元素表示它对应的维度的长度。

print(nparray.shape)
(10,)

从上面的运行结果可以看出,nparray的shape属性返回的元组包含一个元素10,表示这是一个一维数组,第一维有10个元素。更多维度的数组,我们会在后面的课程内容中介绍,先不要着急,我们慢慢学。

#查看数组中的某个元素
nparray[3]
#通过元素下标修改元素的值
nparray[3]=200
print(nparray)
[  0   1   2 200   4   5   6   7   8   9]

注意:numpy中的array不允许向数组中添加不同类型的元素,array中只能存储相同类型的元素

import numpy as np
#在array函数中直接传入一个列表,即可创建数组
nparray = np.array([0,1,2,3,4,5,6,7,8,9]) 
nparray[3]='guowenjing'
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-5-cd7f5e7dd233> in <module>
      2 #在array函数中直接传入一个列表,即可创建数组
      3 nparray = np.array([0,1,2,3,4,5,6,7,8,9])
----> 4 nparray[3]='guowenjing'


ValueError: invalid literal for int() with base 10: 'guowenjing'

如果想窥探array中存储的数据类型,可以使用array提供的dtype属性。

import numpy as np

# 在array函数中直接传入一个列表,即可创建一个数组
nparray = np.array([0,1,2,3,4,5,6,7,8,9]) 

nparray.dtype # 通过dtype得知nparray里存储的元素类型是64位整型
dtype('int32')

创建全0数组

1.使用zeros(num)函数创建一个全零数组,zeros函数需要传入一个参数num,num表示数组中有几个0,也就是元素个数。

import numpy as np
zero_array=np.zeros(10)
print(zero_array)
print(zero_array.dtype)

[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
float64

使用zeros函数创建数组,数组里的元素默认是float64浮点数。如果想设置数组中元素为其他类型,可以在zeros函数中传入dtype=类型

import numpy as np
zero_array=np.zeros(10,dtype=int)
print(zero_array)
print(zero_array.dtype)
[0 0 0 0 0 0 0 0 0 0]
int32

zeros函数传入的第一个参数是一个数字(这个数字表示数组的大小),创建出来的数组只有一行数据,我们称这样的数组为一维数组,或者行向量。向量是一个数学概念,在机器学习中经常会用到很多数学公式,所以在后面的学习中,只要提到行向量就是指一维数组。
zeros函数的第一个参数除了可以是一个数字之外,还尅是一个元组,用于创建多维数组,我们以创建二维数组为例。

import numpy as np
zeros_2=np.zeros((3,5))
print(zeros_2)
[[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]
zeros_2.shape
(3, 5)

通过shape属性返回的元组中有两个元素,就表示zeros_2是一个二维数组,元组的第1个元素表示第一维的长度是3,也就是3行;元组的第2个元素表示第二维的长度是5,也就是有5列。 我们又发现一个规律:一个数组的shape属性返回的元组的元素个数就等于这个数组的维度。有了这个规律,就不用去掰手指数数组的中括号个数了。
其实还可以这样写:

import numpy as np
zeros_2=np.zeros(shape=(3,5))
print(zeros_2)
[[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]

一维数组也被称为行向量,二维数组也被称为矩阵。

创建全1数组

在机器学习中,还会经常用到的一种数组是全1数组,跟全零素组的原理一样,只有数组中的元素从0变成了1.

import numpy as np
np.ones(10)
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
np.ones(shape=(3,5),dtype=int)
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1]])

创建全num数组

上面井道的全0数组和全1数组都有专门的函数直接生产,如果我要生成一个全2、全3、全5…数组该怎么实现呢?
不用担心,numpy为我们提供了full函数,你可以用full函数自定义包含任何数字的全XX数组
使用full函数的语法:full(数组形状,填充的数字),函数的第一个参数数组的形状,一般要传入一个元组来表示数组的形状
需求:创建一个全2的一维数组,数组的大小是10。

import numpy as np
print(np.full((10,),2))
np.full((10,2),3)
[2 2 2 2 2 2 2 2 2 2]





array([[3, 3],
       [3, 3],
       [3, 3],
       [3, 3],
       [3, 3],
       [3, 3],
       [3, 3],
       [3, 3],
       [3, 3],
       [3, 3]])

对于使用full函数创建的一维数组,传入的第一个表示数组形状的参数可以不是元组,可以直接传入一个表示数组中元素个数的数字。

import numpy as np
np.full(10,2)
array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

arrage函数创建数组

如果我想在一个指定的区间范围内,快速创建一个数组,而且我不想自己写循环往数组里一个一个填数据,有没有什么简便的方法呢?
numpy这么强大,当然可以满足这样的小需求。
numpy提供了arrage函数可以在指定的区间范围内,快速生成一个数组,并且按照指定的步长自动填入数据

# 在[0,20)区间内(注意是左闭右开区间,不包含末尾的20),创建一个数组,数组中两个挨着的元素差值是1
# 也就是在[0,20)区间内创建一个数组,并且包含20个整数
np.arange(0,20)
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])

arange函数中的参数介绍:
第1个参数:开始值,包含;
第2个参数:结束值,不包含;
第3个参数:步长,默认值1。


np.arange(1,20,2)
array([ 1,  3,  5,  7,  9, 11, 13, 15, 17, 19])

我们还可以在调用arange函数的时候只传入一个数字num,这时候就会生成一个一维数组,数组里的元素默认是在[0,num)区间内,相邻两个元素之间的差值是1,也就是使用默认步长生成的数组元素,看个例子就明白了。
不能创建二维数组

np.arange(20)
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])

randint随机数数组

接下来我要讲的一个知识点是随机数,随机数在我们的生活中经常使用,比如公司年会抽奖,在所有的员工中随机抽取一个幸运的员工获得年终大奖,为了保证公平公正,程序员小哥哥就要写个随机数程序,从全体员工中随机挑选一个员工。
numpy中有个专门模块用于处理随机数相关的操作,它就是random模块,random模块已经给我们实现好了一些生成随机数的函数,接下来我们学习几个常用的生成随机数的函数。
需求:在一个区间内生成整数随机数。

np.random.randint(1,20)
17

randint还可以传入第3个参数size,用于设置生成的随机数个数。 如果将size设置成一个整数,那么返回的是一个一维数组(向量)。 如果将size设置成一个元组,那么返回的是一个多维数组(矩阵)。

#生成一个一维数组
print(np.random.randint(1,20,size=4))
#写法2
print(np.random.randint(1,20,4))
#生成一个二维数组
np.random.randint(1,20,size=(3,4))
[16  6 18 16]
[18 12 17 12]





array([[10, 18,  5,  6],
       [ 1,  4,  6,  3],
       [ 7, 13, 13,  7]])

需求:要求每次生成的随机数相同
这个需求非常容易实现,numpy的random模块给我们提供了一个叫做随机种子的函数seed,在使用seed函数的时候需要传入一个数字,这个数字可以随意传,我们可以把这个数字理解成种子“编号”,这样就能够保证使用同一个“编号”的种子生成的随机数是相同的。

import numpy as np

np.random.seed(111)
print("使用111种子生成的随机向量:", np.random.randint(0,10,5))
np.random.seed(111)
print("使用111种子生成的随机向量:", np.random.randint(0,10,5))

#np.random.seed(21)
print("使用21种子生成的随机向量:", np.random.randint(0,10,5))
使用111种子生成的随机向量: [4 4 4 6 3]
使用111种子生成的随机向量: [4 4 4 6 3]
使用21种子生成的随机向量: [9 2 6 2 8]

reshape改变数组形状

之前我们将讲解过,通过数组的shape属性可以查看数组的形状,如果想改变数组的形状可以使用reshape函数,我们来看看reshape函数具体怎么来使用。

import numpy as np

# 创建一个包含6个数字的一维数组
x1 = np.random.randint(0,10,6)
print("x1 shape :", x1.shape)
print(x1)

# 将数组x1转换成一个2行3列的二维数组
x2 = x1.reshape(2,3)

print("-------------------------") #打印一个分割线,只为了方便看打印结果
print("x1 shape :", x1.shape)
print(x1)

print("x2 shape :", x2.shape)
print(x2)
x1 shape : (6,)
[7 9 7 1 0 8]
-------------------------
x1 shape : (6,)
[7 9 7 1 0 8]
x2 shape : (2, 3)
[[7 9 7]
 [1 0 8]]

x1.shape返回的是一个包含1个元素的元组,表示x1是一个一维数组,数组里有6个元素。
x2.shape返回的是一个包含2个元素的元组,表示x2是一个两行三列的二维数组,x2是使用reshape函数在x1的基础上转换得到的新数组,原数组x1没有发生改变。
使用reshape函数改变数组形状生成一个新的数组的时候,原数组中的元素个数要正好填满新数组,例如,数组x1有6个元素,数组x2的形状是2行3列,要想填满数组x2就必须有6个元素,正好x1有6个元素,所以使用reshape转换数组形状能成功。

import numpy as np

# 创建一个包含6个数字的一维数组
x1 = np.random.randint(0,10,6)

# 错误例子1,x1的元素个数不够填满新的数组
x4 = x1.reshape(4,2)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-32-e1d4ce812591> in <module>
      5 
      6 # 错误例子1,x1的元素个数不够填满新的数组
----> 7 x4 = x1.reshape(4,2)


ValueError: cannot reshape array of size 6 into shape (4,2)
import numpy as np

# 创建一个包含6个数字的一维数组
x1 = np.random.randint(0,10,6)
 
# 错误例子2,x1的元素个数超过了新数组需要的元素个数
x4 = x1.reshape(2,2)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-33-40152e3b359c> in <module>
      5 
      6 # 错误例子2,x1的元素个数超过了新数组需要的元素个数
----> 7 x4 = x1.reshape(2,2)


ValueError: cannot reshape array of size 6 into shape (2,2)

在使用reshape的时候,如果你不关心转换之后有多少行或者有多少列,应该怎么操作呢?下面我用几个例子来演示下reshape的新用法。
需求1:x1是一个包含6个元素的一维数组,现在我基于x1使用reshape转换生成一个新数组,我要求新数组只要有2行就行,具体有几列我不关心

import numpy as np

# 创建一个包含6个数字的一维数组
x1 = np.random.randint(0,10,6)

x1.reshape(2,-1)
array([[3, 7, 9],
       [3, 1, 6]])

从这个需求的代码实现可以看出,在使用reshape的时候,不关心的维度可以使用-1表示,让机器自动去判断。
需求2:x1是一个包含6个元素的一维数组,现在我基于x1使用reshape转换生成一个新数组,我要求新数组只要有2列就行,具体有几行我不关心

import numpy as np

# 创建一个包含6个数字的一维数组
x1 = np.random.randint(0,10,6)

x1.reshape(-1,2)
array([[8, 5],
       [4, 1],
       [1, 7]])

通过这个需求,再一次验证了上一个需求的结论,我不关心有多少行,那么控制行的参数就传-1,让机器自己去判断转换之后的新数组有多少行。
我们在前面学习了使用数组的shape属性可以查看数组的形状,除了shape属性之外,还有两个比较常用的属性,分别是查看数组维度的ndim属性和查看数组元素个数的size属性。

import numpy as np

# 创建一个包含6个数字的一维数组
x1 = np.random.randint(0,10,6)

x6 = np.random.randint(0,10,6)
print("x6是{}维数组".format(x6.ndim))
print("x6中有{}个元素".format(x6.size))

x7 = x6.reshape((3,2))
print("x7是{}维数组".format(x7.ndim))
print("x7中有{}个元素".format(x7.size))
x6是1维数组
x6中有6个元素
x7是2维数组
x7中有6个元素

数组切片

我们在前面学习了通过数组下标获取数组的某个元素,这种方式只能获取一个元素,如果想获取数组中的一批元素或者一个片段的元素应该怎么操作呢?
numpy为我们提供了好用到爆的切片功能,老规矩直接上例子代码。

import numpy as np

# 创建一个一维数组:[0 1 2 3 4 5 6 7 8 9]
arr1 = np.arange(10)
print(arr1)
[0 1 2 3 4 5 6 7 8 9]

需求1:获取arr1的前5个元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oSfR0hdS-1586510375002)(./1.png)]

import numpy as np

# 创建一个一维数组:[0 1 2 3 4 5 6 7 8 9]
arr1 = np.arange(10)

arr1[:5]
array([0, 1, 2, 3, 4])

我们只用了一行代码就完成了获取arr1的前5个元素的需求,通过这行代码我们也看出了切片的语法:数组名[开始下标:结束下标]
切片的语法有两个注意点: 1)如果切片是从第一个下标0开始,可以不写开始下标; 2)切片不包含结束下标对应的数组元素;

需求2:获取arr1的后3个元素
2

import numpy as np

# 创建一个一维数组:[0 1 2 3 4 5 6 7 8 9]
arr1 = np.arange(10)

arr1[7:]
array([7, 8, 9])

数组的下标从0开始,数组arr1中共有10个元素,arr1最后一个元素的脚标是9,要完成需求是获取arr1的后3个元素,那么脚标就是从7开始。

实现这个需求有个注意点:切片的结束下标如果不写的话,表示切片到数组的结尾。

需求3:获取arr1的第3个到第6个元素
3

import numpy as np

# 创建一个一维数组:[0 1 2 3 4 5 6 7 8 9]
arr1 = np.arange(10)

arr1[2:6]
array([2, 3, 4, 5])

数组的下标从0开始,第3个元素的下标是2,第6个元素的下标是5,要获取到第6个元素,也就是说切片的结果要包含第6个元素,由于切片是不包含结束下标对应的元素的,所以切片的结束下标要设置成第6个元素后一个下标的位置。
解释这么多!弄得这么绕!全怪数组的下标从0开始!
需求4:从数组arr1中,隔一个元素获取一个

在这里插入图片描述
小提示:切片带步长的语法是:数组名[开始下标:结束下标:步长]

import numpy as np

# 创建一个一维数组:[0 1 2 3 4 5 6 7 8 9]
arr1 = np.arange(10)

arr1[::2]
array([0, 2, 4, 6, 8])

因为是要从头取到尾,默认切片不设置开始和结束下标就表示从第1个元素到最后1个,上面的代码等价于设置开始和结束下标的方式:arr1[0:10:2]
由于需求是隔一个元素获取一个,中间要跳过一个元素,所以要设置步长为2。
需求5:从后向前获取数组arr1中的元素,相当于把数组arr1翻过来

5

import numpy as np

# 创建一个一维数组:[0 1 2 3 4 5 6 7 8 9]
arr1 = np.arange(10)

arr1[::-1]
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])

步长是正数表示从左向右获取,步长是负数表示从右向左获取。需求是把数组翻过来,那就是从右向左获取,而且要获取原数组arr1的所有元素,所以步长设置为-1。
上面的5个需求的实现方法能够全部掌握了,基本上可以熟练地使用数组切片了。
切片不是一维数组的特有功能,多维数组同样可以使用切片,接下来我们以最常用的二维数组为例,讲解在二维数组中是如何使用切片的。

import numpy as np

# 先创建一个3行5列的二维数组
arr2 = np.arange(15).reshape((3,5))

print(arr2)
print("arr2是{}维数组".format(arr2.ndim))
print("arr2有{}个元素".format(arr2.size))
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
arr2是2维数组
arr2有15个元素

新需求1:获取数组arr2的前2行的前3列
在这里插入图片描述

import numpy as np

# 先创建一个3行5列的二维数组
arr2 = np.arange(15).reshape((3,5))

arr2[:2,:3]
array([[0, 1, 2],
       [5, 6, 7]])

这里不再像df或者Series用loc或者iloc获取元素,直接使用数组名加中括号就可以定位到具体的元素
二维数组的切片语法:数组[第一维开始下标:第一维结束下标,第二维开始下标:第二维结束下标]

我们从二维数组的切片语法可以看出中括号内以逗号分隔,逗号前的开始/结束下标控制第一维切片,逗号后的开始/结束下标控制第二维。其他切片相关的语法规则跟前面一维数组的规则一样。
需求是先获取arr2的前2行,通过切片中设置第一维的开始/结束下标控制;然后再获取前两行的前三列,通过切片中设置第二维的开始/结束下标控制。
新需求2:隔一行取一行,再隔一列取一列

在这里插入图片描述

import numpy as np

# 先创建一个3行5列的二维数组
arr2 = np.arange(15).reshape((3,5))

arr2[::2,::2]
array([[ 0,  2,  4],
       [10, 12, 14]])

通过这个需求的实现,我们可以得出一个结论,使用数组切片的时候,不管数组有多少维,每一个维度的切片都是使用相同语法规则的切片表达式控制。

作业

1.创建一个包含10个整数0的一维数组,创建完后修改数组中第5个元素的值为10
2.创建一个3行5列的二维数组,获取数组arr2的前2行的前3列

import numpy as np
zero_array=np.zeros(10,dtype=int)
zero_array[4]=10
print(zero_array.dtype)
zero_array
int32





array([ 0,  0,  0,  0, 10,  0,  0,  0,  0,  0])
arr2=np.random.randint(0,10,(3,5))
arr2=np.random.randint(0,10,size=(3,5))
print(arr2)
#获取数组arr2的前2行的前3列
arr2[:2,:3]
[[4 3 5 0 8]
 [2 2 8 1 1]
 [6 3 8 9 4]]





array([[4, 3, 5],
       [2, 2, 8]])

### 关于 NumPy 切片操作的练习题目 #### 创建多维数组并进行切片操作 创建一个多维数组,并对其进行不同类型的切片操作,可以更好地理解 NumPy 的切片机制。 ```python import numpy as np # 创建一个 3x4 数组 arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) print("原始数组:") print(arr) # 获取第二行的数据 row_2 = arr[1, :] print("\n第二行数据:") print(row_2) # 获取第三列的数据 column_3 = arr[:, 2] print("\n第三列数据:") print(column_3) ``` #### 使用负数索引进行切片 利用负数索引来访问数组中的元素或子集是一个常见的技巧,在某些情况下可以使代码更加简洁易读。 ```python # 获取最后一行的数据 last_row = arr[-1, :] print("\n最后一行数据(使用负数索引):") print(last_row) # 获取倒数第二个元素所在的整列 second_last_column = arr[:, -2] print("\n倒数第二列数据(使用负数索引):") print(second_last_column) ``` #### 对三维及以上维度的数组进行切片 对于更高维度的数组来说,掌握其切片方法同样重要。下面的例子展示了如何处理三维数组。 ```python # 创建一个 2x3x4 的三维数组 three_d_arr = np.arange(24).reshape((2, 3, 4)) print("三维数组:") print(three_d_arr) # 访问第一个二维矩阵的最后一行 slice_three_d = three_d_arr[0, -1, :] print("\n第一个二维矩阵的最后一行:") print(slice_three_d) ``` 通过上述例子可以看出,NumPy 提供了灵活而强大的切片功能来帮助用户高效地操作数值型数据结构[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值