如何高效地用Numpy 生成各种各样的数组?

现在我们对 Numpy 有了基本的了解,利用 Numpy 能够帮助我们提高计算效率,利用 Numpy 的 ndarray 多维数组对象存储数据能够减少内存占用,Numpy 的这些优势使得它广泛应用于人工智能、计算机视觉、生物信息等领域。 使用Numpy进行数据处理和科学计算时,生成各种类型的数组是非常常见的需求,有的需要全 0 数组,有的需要满足正态分布的数组。Numpy提供了多种函数和方法,可以方便地生成不同形状和类型的数组。今天我就带大家学习一下如何利用 Numpy 生成各种各样的数组。

生成 0 和 1 的数组

我们知道在图像处理中,我们通常是借助矩阵来表示图片的颜色,全 0 数组表示黑色,全 1 数组表示白色;在数据处理过程中,有时也需要借助全 0 或全 1 数组表示边界条件和权重。

下面我们就来看看如何利用 Numpy 生成一个全 0 或全 1 数组吧!

zeros 方法创建全 0 数组

我们先来学习一下如何生成一个全 0 数组吧!

比如在植物大战僵尸中,游戏开始时,草坪上没有植物,这时我们便可以通过一个全 0 数组代表草坪的初始状态。现在我们需要初始化一个六行八列的草坪,该如何实现呢?

代码示例:

Python 复制代码
import numpy as np  
zeroArry=np.zeros((6,8))  
print(zeroArry)

输出结果:

css 复制代码
[[0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]]

可以看见在利用 zeros 方法创建一个全 0 数组时,我们只需要传入所需数组的形状便可以创建出所需形状的全 0 数组。

学习完了如何创建全 0 数组,下面我们再来看看如何创建全 1 数组吧!

ones 方法创建全 1 数组

全 1 数组与全 0 数组的作用基本相同,同样也可以用于数据的初始化。比如,扫雷游戏,开始时整个地图我们都没有查看过,这时我们便可是设置一个全 1 数组表示这一初始状态,现在我们要初始化一个四行三列的地图该如何处理呢?

代码示例:

Python 复制代码
import numpy as np  
oneArry=np.ones((3,4))  
print(oneArry)

输出结果:

lua 复制代码
[[1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]]

同创建全 0 数组一样,我们只需传入所需数组的形状即可创建所需形状的全 1 数组。我们可以看到,不管是 0 填充还是 1 填充,默认的数据类型都是为浮点数,这值得我们注意。

同时在一些情况下,我们可能需要预先分配足够的空间以容纳即将到来的数据时,这时我们就需要创建一个未初始化的空数组来完成,那么如何才能创建一个指定形状的空数组呢?

empty 方法创建未初始化数组

empty 方法是用来创建一个指定形状、指定数据类型并且未初始化的数组。未初始化指的就是对于其中的数据并没有被指定填充值

比如,在实验中我们还并未知晓实验数据,但需要提前分配一个三行四列的地址空间,该如何处理呢?代码示例:

Python 复制代码
import numpy as np  
emptyArry=np.empty((3,4))  
print(emptyArry)

输出结果:

lua 复制代码
[[6.23042070e-307 4.67296746e-307 1.69121096e-306 4.67293691e-307]
 [2.22518251e-306 1.60218491e-306 1.37962320e-306 1.78019354e-306]
 [2.22522597e-306 1.33511969e-306 1.15711378e-306 1.16826224e-307]]

可以看到其中会出现数据,我们之前不是说没有指定填充值吗,这里为什么又会出现值呢?这其实不难理解,未初始化并不代表没有值,为了程序的安全,未初始化的变量程序会根据编译器的设置填充一些值,比如这里的随机值

此外,在数学中,特别是在物理中,我们知道一些数据都是存在一些规律的,在进行一些模拟验证时也是需要这样一些具有规律的数据,用键盘一个一个输入这些数据往往是不现实的,NumPy 作为科学计算的利器,也是将这类数据考虑其中,建立相对应的方法。比如:我们想要创建一个对角矩阵该如何处理呢?

eye 方法创建对角数组

线性代数的对角矩阵(首先数组是方阵,即 n×n,其次是对角线全为 1,其余位置都为 0),由于对角矩阵具有特殊的性质,能够简化运算,所以在计算时用到的时候很多,NumPy 当然也不会放过这个特殊的矩阵,创造了 eye() 函数来创建对角矩阵。

比如,我们要创建一个五行五列的对角矩阵该如何处理呢?

代码示例:

Python 复制代码
import numpy as np  
eyeArry=np.eye(5)  
print(eyeArry)

输出结果:

css 复制代码
[[1. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 1.]]

可以看见,利用 eye 方法我们成功创建了对角矩阵并且默认数据类型为浮点型。

到这里,利用 Numpy 创建一些特殊的矩阵我们就介绍完了,下面我们再来看看如何利用已有数组生成新数组呢?

从现有数组中生成新数组

利用现有数组生成新数组的方式大概有三种方法,分别为 array 方法asarray 方法以及 copy 方法。下面我们就来看看如何利用这三种方法生成新数组吧!

array 方法

首先我们先来看看 array 方法,看看如何借此方法生成新数组。

方法:numpy.array(object,dtype,shape)

  • object 为要转化为 Numpy 数组的数据对象,可以为列表、元组或者数组;
  • dtype 为转化后数组的数据类型,若不设置则与原数据对象的数据类型保持一致;
  • shape 用于指定数组的形状,若不设置则与原数据对象的 shape 相同。

下面我们就来看看如何利用 array 方法生成新数组。

代码示例:

Python 复制代码
import numpy as np  
arr1=np.array([1,2,3,4,5])  
arr2=np.array(arr1)  
print(arr2)

输出结果:

csharp 复制代码
[1 2 3 4 5]

可以看见,我们利用 array 方法,成功借助 arr1 数组生成了 arr2 这个新数组,新数组的数据与原数组相同,数据类型也相同。下面我们再来看看如何利用 asarray 方法生成新数组。

asarray 方法

方法:numpy.asarray(object,dtype)

  • object 为要转化为 Numpy 数组的数据对象,可以为列表、元组或者数组;
  • dtype 为转化后数组的数据类型,若不设置则与原数据对象的数据类型保持一致。

下面我们就来看一下如何利用 asarray 函数生成新数组吧!

代码示例:

Python 复制代码
import numpy as np  
arr1=np.array([1,2,3,4,5])  
arr3=np.asarray(arr1)  
print(arr3)

输出结果:

csharp 复制代码
[1 2 3 4 5]

可以看见,借助 asarray 方法我们也成功生成了新数组。下面我们再来看看如何利用 copy 方法生成新数组呢!

copy 方法

方法:numpy.copy(object)

  • object 为要创建副本的数据对象,可以为列表、元组或者数组。

下面我们就来看看如何利用 copy 函数生成新的数组吧!

代码示例:

Python 复制代码
import numpy as np  
arr1=np.array([1,2,3,4,5])  
arr4=np.copy(arr1)  
print(arr4)

输出结果:

csharp 复制代码
[1 2 3 4 5]

通过观察以上三个案例,我们发现它们生成新数组的操作是基本相同的,但是它们是否有什么区别呢?下面我们就通过个案例带领大家了解。

当我们用原数组生成新数组后,对原数组进行修改新数组是否会改变呢?让我们来一起看看吧!

代码示例:

Python 复制代码
import numpy as np  
arr1=np.array([1,2,3,4,5])  
arr2=np.array(arr1)  
arr3=np.asarray(arr1)  
arr4=np.copy(arr1)  
arr1[0]=100  
print('更改后arr2为:',arr2)  
print('更改后arr3为:',arr3)  
print('更改后arr4为:',arr4)

输出结果:

ini 复制代码
更改后arr2为: [1 2 3 4 5]
更改后arr3为: [100   2   3   4   5]
更改后arr4为: [1 2 3 4 5]

可以看见,对原数组的第一个数据进行修改之后,利用 array 和 copy 方法生成的新数组并没有被修改,而利用 asarray 方法生成的新数组则发生了同样的改变。

当涉及Numpy数组的复制和创建新数组时,了解array、copy和asarray方法之间的区别是很重要的。它们在生成新数组时有不同的行为和影响,主要区别如下:

array方法:

行为:array方法创建原始数组的副本,即进行深拷贝。

影响:生成的新数组与原始数组完全独立,修改新数组不会影响原始数组,新数组和原数组在内存中拥有不同的地址。

copy方法:

行为:copy方法创建原始数组的副本,同样进行深拷贝。

影响:生成的新数组与原始数组完全独立,修改新数组不会影响原始数组,新数组和原数组在内存中拥有不同的地址。

asarray方法:

行为:asarray方法创建原始数组的视图,即进行浅拷贝。如果原始数组是Numpy数组,则不会复制数据,而只是共享相同的数据存储。如果原始数组是普通的Python列表或元组,则会复制数据。

影响:生成的新数组与原始数组共享相同的数据存储,修改新数组将会影响原始数组。新数组和原数组在内存中具有相同的地址,但数据是否共享取决于原始数组的类型。

它们三者的区别在于生成的新数组和原始数组在内存中的关系以及是否共享数据存储。如果需要创建完全独立的数组,应使用array或copy方法。如果需要共享数据存储或希望节省内存,可以考虑使用asarray方法。

由此,我们知道:array 和 copy 方法生成的是原数组的副本,是对原数组进行的深拷贝,新数组的内存地址与原数组是不同的;asarray 是对原数组进行的浅拷贝,它是原数组的视图,新数组的内存地址与原数组的内存地址是相同的。

下面我们就来学习生成数组的另一种方法------生成固定范围的数组。

生成固定范围的数组

生成固定的数组即生成包含我们所需范围内的数据的数组,主要有两种方法分别为 linspace 方法arange 方法

linspace 方法

方法:linspace(start,stop,num)

  • start 为数据的起始点。
  • stop 为数据的结束点。
  • num 为等步长生成的数据量。

下面我们就利用该方法生成一个数组,起始点为 0,结束点为 100,数据量为 5 的数组吧!

代码示例:

Python 复制代码
import numpy as np  
arr=np.linspace(0,100,5)  
print(arr)

输出结果:

css 复制代码
[  0.  25.  50.  75. 100.]

可以看见,我们成功得到了一个数据量为 5 的等距数组,默认数据类型为浮点型。同时,我们可以看见生成的数组是包括了我们设置的数据范围的边界的,我们可以简记为"左闭右闭"原则。在数学上,如果我们需要生成一定范围内的指定数据量的等距数组时便可以通过该方法获取

下面我们再来看看如何利用 arange 生成指定范围的数组吧!

arange 方法

方法:arange(start,stop,step,dtype)

  • start 为数据起始点。
  • stop 为数据终点。
  • step 为数据之间的步长,默认为 1。
  • dtype 用于指定数组的数据类型,默认为浮点型。

下面我们就来通过该方法生成一个范围 0-100、数据步长为 5 的等差数列吧!

代码示例:

Python 复制代码
import numpy as np  
arr=np.arange(0,100,5)  
print(arr)

输出结果:

css 复制代码
[ 0  5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95]

可以看见,利用 arange 函数,我们能够生成一定数据范围内的等差数列,我们发现该方法生成的数组的数据类型为整型,并且并没有包括边界值,我们可以简记为"左闭右开"。在处理数学问题时,我们可以借助该方法生成一定数据范围内的等差数列

通过上述两个案例,我们可以发现:linspace 方法用于生成一定数据范围内的所需数据量的数组,默认数据类型为浮点型,生成的数据包括数据边界;arange 方法用于生成一定范围内的指定步长的等差数列,默认数据类型为整型,生成的数据不包括数据边界。

学习了生成固定范围的数组,下面我们再来学习一下如何生成随机的数组吧!

生成随机数组

当我们处理大量数据或需要进行随机实验时,随机数组是不可或缺的工具。

随机数组是指由随机数组成的数组,它广泛应用于各种领域,例如统计学、数据分析、模拟、游戏开发等。例如:在角色扮演游戏中,我们可以使用随机数组生成随机的战斗伤害、经验值或掉落物品,以增加游戏的趣味性和可玩性;在电路模拟中,我们可以使用随机数组生成随机的噪声信号,以评估电路的性能和稳定性。

在利用 Numpy 生成随机数组时,我们需要借助 random 模块。NumPy 的 random 模块提供了一个用于生成随机数的强大工具集。它包含了各种函数和类,可以用于生成不同类型的随机数,如整数、浮点数和随机数组,此外还可以用于生成符合各种概率分布的数组。

下面我们就来看看如何利用 Numpy 的 random 模块生成符合各种概率分布的数组吧!

均匀分布随机数组

生成均匀分布随机数组主要有 rand 方法和 uniform 两种方法。

首先我们来看看如何利用 random 生成符合均匀分布的随机数组呢。

rand 方法

rand 用于生成 0-1 区间内指定数量的均匀分布的随机数组。

方法:rand(shape,dtype)

  • shape 为数组的形状。
  • dtype 为数组的数据类型,默认为浮点型。

比如,在游戏中,要求击杀野怪后会爆 15 个装备之一,我们便可以利用 rand 方法生成一个数值范围 0-1 的符合均匀分布的大小为 15 的数组来表示各个装备出现的概率。

代码示例:

Python 复制代码
import numpy as np  
arr=np.random.rand(15)  
print(arr)****

输出结果:

csharp 复制代码
[0.62143845 0.12778872 0.87422787 0.95940872 0.66958581 0.15454008
 0.76071261 0.15836626 0.77351804 0.87778616 0.20672373 0.85318471
 0.98831228 0.21829142 0.83702802]

可以看见,我们成功得到了数据量为 15 符合均匀分布的装备概率数组,据此来决定刷怪后出现什么装备。不过该方法的缺点就是只能生成数据范围 0-1 内的均匀分布数组。

下面我们再来看看 uniform 有什么不同呢。

uniform 方法

uniform 方法用于生成指定范围内的均匀分布的数组,相较于 rand 方法更为灵活。

方法:uniform(low,high,size)

  • size 为数组的形状。
  • low 为随机数的最小值。
  • high 为随机数的最大值。

比如:我们在游戏中,往往会遇到吃一个果子既可能中毒减少血量,也可能治疗增加血量,这时候我们就可以利用该函数实现。比如最大减血量为 100,最大加血量为 100,怎样得到这个范围内的随机数呢?

代码示例:

Python 复制代码
import numpy as np  
arr=np.random.uniform(-100,100,1)  
print(arr)

输出结果:

csharp 复制代码
[18.41991632]

可以看见,该结果就代表给玩家增加 18.41991632 的血量。通过案例,我们知道利用 uniform 生成均匀分布的随机数组要更为灵活,它除了可以生成 0-1 内的均匀分布数组外,还可以生成其他范围内的均匀分布数组。

下面我们再来学习一下如何生成一组符合正态分布的数组呢。

正态分布随机数组

生成正态分布数组的方法组要有两种,分别为 normal 方法和 standard_normal 方法。

下面我们就先从 normal 方法开始看看如何利用这些方法生成正态分布的数组。

normal 方法

方法:normal(loc,scale,size)

  • loc 为正态分布数组的均值,
  • scale 为数组的方差,
  • 通过 size 属性我们能够设置数组的形状或者数据量。

通常一个班级同学的成绩是符合正态分布的,下面我们就用 normal 模拟一个班级的期末成绩,其中均值为 60,方差为 81,学生人数为 20 人。

代码示例:

Python 复制代码
import numpy as np  
score=np.random.normal(60,9,20)  
print(score)

输出结果:

csharp 复制代码
[61.06296251 62.24716851 60.59643633 61.66150912 54.31424568 50.0636896
 85.25668733 65.97137913 74.13954099 59.70926632 32.06950931 55.49741382
 67.09152988 52.56268941 44.34325786 58.75831326 68.99711559 58.05501051
 52.57707606 61.42147338]

可以看见,利用上述方法我们成功生成了一组符合正态分布的学生成绩。normal 方法的优点就在于非常灵活,我们可以根据自己需求设置数组的方差和均值

下面我们再来看看如何利用 standard_normal 方法生成正态分布数组吧!

standard_normal 方法

利用 standard_normal 方法用于生成指定形状的符合标准正态分布的数组,该方法与 normal 方法相比不是很灵活,但是参数较少,我们只需要指定数组形状便可以生成指定形状的标准正态分布的数组。

方法:standard_normal(size)

  • size 为随机数组的形状。

在机器学习中,生成一组符合标准正态分布的数组可以用于初始化模型的参数,特别是对于需要随机初始化的算法,例如随机梯度下降等。通过将参数初始化为标准正态分布,可以帮助模型更好地收敛到最优解,并提高模型的性能和准确性。

下面我们就生成一个形状为三行四列的符合标准正态分布的数组,用于实现模型参数的初始化。

代码示例:

Python 复制代码
import numpy as np  
arr=np.random.standard_normal((3,4))  
print(arr)

输出结果:

lua 复制代码
[[-0.05899553 -1.0534277  -1.18875175  0.91898097]
 [-0.58510129  2.3321576   1.00022868 -0.11486971]
 [ 3.02941126 -0.72335555  0.71833573 -0.30375334]]

可以看见我们成功生成了标准正态分布的二维数组。

学习生成随机数组能够帮助我们更好地解决生活中遇到的随机问题,通过 Numpy 生成符合要求的数组,进而随机情况。

到这里,如何利用 Numpy 生成各种各样的数组我们就介绍完成了,大家可以仔细学习相关方法,因为 Numpy 的一切数据处理方法都是在创建的数组上进行应用的。

总结

Numpy 的 ndarray 数组对象是 Numpy 最为核心的数据对象,Numpy 的一切数据处理方法都是在 ndarray 对象上应用的,所以学习创建 ndarray 数组非常重要。

在图片处理等领域,我们可以利用 zeros 和 ones 函数生成全 1 或全 0 数组来代表黑色图片以及白色图片。在处理一些物理问题时,往往需要借助一些特殊的矩阵,这时我们可以借助 eye 方法生成符合要求的对角矩阵。当我们需要为数据预先分配内存时,可以借助 empty 生成空数组,对内存空间进行预分配。

利用已有数组生成新数组时,array 和 copy 方法生成的是原数组的副本,是对原数组进行的深拷贝,新数组的内存地址与原数组是不同的;asarray 是对原数组进行的浅拷贝,它是原数组的视图,新数组的内存地址与原数组的内存地址是相同的。

如果想要生成指定个数的等距数组,我们可以使用 linspace 方法,要注意该方法生成的数组是包括边界值的;如果想要设置数据之间的步长,我们可以借助 arange 方法,该方法生成的数组是不包括边界值的。

在处理概率论问题时,如果想要生成均匀分布的数组,我推荐大家使用 uniform 方法,该方法能够指定数据范围,使用起来相对灵活;如果想要生成符合正态分布的数组,我推荐大家使用 normal 方法,利用该方法我们能够指定数组的方差和均值,使用起来也比较灵活,既可以生成符合标准正态分布的数组,也可以生成符合其他类型的正态分布的数组。

本篇文章来源小册《基于 Python 的数据分析与可视化juejin.cn/book/724073...

相关推荐
hanglove_lucky17 分钟前
本地摄像头视频流在html中打开
前端·后端·html
皓木.2 小时前
(自用)配置文件优先级、SpringBoot原理、Maven私服
java·spring boot·后端
i7i8i9com2 小时前
java 1.8+springboot文件上传+vue3+ts+antdv
java·spring boot·后端
秋意钟2 小时前
Spring框架处理时间类型格式
java·后端·spring
我叫啥都行2 小时前
计算机基础复习12.22
java·jvm·redis·后端·mysql
Stark、2 小时前
【Linux】文件IO--fcntl/lseek/阻塞与非阻塞/文件偏移
linux·运维·服务器·c语言·后端
小华同学ai2 小时前
ShowDoc:Star12.3k,福利项目,个人小团队的在线文档“简单、易用、轻量化”还专门针对API文档、技术文档做了优化
前端·程序员·github
coding侠客3 小时前
Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘
java·spring boot·后端
37手游后端团队4 小时前
谈谈golang的错误处理
后端