Numpy(numberical python)

一、初识numpy

数值统计模块。numpy是数据用于科学计算的基础,既能完成科学计算服务,还能被用作高效的多维数据容器。主要用来存储处理高维矩阵或数组。
用作存储容器时,任何数据类型均可存储,但是一个数组中元素必须是同种数据类型。
特点:运算快、节省空间。

二、安装numpy

numpy并非是python中的内置模块,所以需要安装。

1. 使用pip安装

在终端输入安装命令:

pip install numpy

如果安装速度很慢,可以指定国内镜像源,我日常使用最多的是清华源。安装命令如下:

pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
2.使用Anaconda沙箱环境

anaconda俗称python全家桶,包含了很多python环境,你需要什么样的环境就创建什么样的。Anaconda可以创建多个环境,且环境之间是独立的,互不影响。
Anaconda访问官网找到下载链接安装即可,基本都是默认下一步(如果你不修改安装路径的话)。

  • 创建沙箱环境
conda create -n 沙箱环境名 python=python版本号
  • 激活沙箱环境
activate 沙箱环境名

最后给numpy项目指定沙箱环境即可。anaconda环境中默认包含numpy模块,不需要再安装。

三、使用numpy

import numpy as np(推荐)
或
from numpy import *

四、矩阵

1. 矩阵的创建
np.mat()
mat1 = np.mat("1 2 3; 4 5 6; 7 8 9")
print(mat1)
print(type(mat1))
"""
运行结果:
[[1 2 3]
 [4 5 6]
 [7 8 9]]
<class 'numpy.matrix'>
"""
2. 矩阵的属性

属性名称

属性介绍

shape

矩阵的结构

ndim

矩阵的维度

size

矩阵的元素个数

dtype

矩阵的元素类型

注意:这是矩阵的属性,并非是方法,所以直接使用矩阵名.属性名即可,不要添加括号。

3.矩阵的计算

方式

介绍

mat1+mat2

两个矩阵相加

mat1-mat2

两个矩阵相减

n*mat2

矩阵的数乘

mat.T

矩阵的转置

mat.I

矩阵的逆矩阵

np.multiply(mat1,mat2)

两个矩阵对应元素相乘

五、N维数组

N维数组,又称“多维数组”,这里的N指的就是数组的维度。

1. 数组和列表的区别

Numpy多维数组和列表在表现形式上很像:元素都是由中括号包裹的。然而,两者是完全不同的两种数据类型,在使用时一定要区分开来。两者不同点:

  • 数组在创建时,形状大小就已经固定;而列表是可变的。改变数组的大小,实际上是删除了原来的数组,创建了一个新数组。
  • 数组中的元素要求是同种数据类型,因此在内存中实际的大小也是相同的。除非数组是由Python的各种对象组成,这样元素内存大小才不同。
arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([1, '2', 3, 4])
print(arr1) # [1 2 3 4]
print(arr2) # ['1' '2' '3' '4']
print(type(arr1))   # <class 'numpy.ndarray'>
  • 数组对大量数据进行操作时,更加方便高效,代码量也更少。
2.ndarray

ndarray是numpy提供的一种内存连续的、存储单一数据类型的、可以存储多维数组的对象。有两种存储方式:

  • C(C语言风格) ————> 行优先存储
  • F(Fortran语言风格) ————> 列优先存储
3. 数组的创建
(1)自定义数组
np.array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0)

参数介绍:
object:接收array。表示想要创建的数组(一维或多维)
dtype:接收data-type。表示数组所需的数据类型。
ndmin:接收int。指定生成数组应该具有的最小维数。
# 一维数组
arr1 = np.array([1, 2, 3, 4])
# 二维数组
arr2 = np.array([[1, 2, 3], [0, 1, 2], [2, 3, 1]])
# 列向量类型的数组
arr3 = np.array([[1], [2], [3], [4]])
(2)特殊数组

方法

描述

arange(start, stop, step, dtype)

创建一维数组。start默认为0,stop默认为1.

linspace(start,stop,num,endpoint=True)

创建等差数组。默认为float类型。num:元素的个数,默认50. endpoint:默认为True,表示包含结束位置。

logspace(start, stop, num, base)

创建等比数组。start:首项的指数。stop:尾项的指数。base:底数,默认为10.0

zeros(shape,dtype,order=‘C’)

创建全0数组。shape:数组的形状,接收元组。order=‘C’:横向 order=‘F’:纵向

ones(shape,dtype,order=‘C’)

创建全1数组。

diag(v,k=0)

创建对角数组。v:接收array或list。

eye(m,n)

创建单位数组。m:行数。n:列数。只写一个数默认行列相同。

# (1)arange:类似于range
arr6 = np.arange(1, 10, 1)
print(arr6)

# (2)等差数列
# np.linspace()
# endpoint=True:表示等差数列,在start与stop之间插入n-2个值,n为数值的个数
# endpoint=False:表示等差数列,在start与stop之间插入n-1个值,表示平均分成n份(为线段的个数)
arr7 = np.linspace(2, 5, 5)
print(arr7)

# (3)等比数列
arr8 = np.logspace(0, 2, 3)
print(arr8)
arr = np.logspace(1, 11, 6, base=3)
print(arr)
arr = np.logspace(1 / 2, 11 / 2, 6, base=9)
print(arr)
arr = np.logspace(np.log10(2), np.log10(162), 5)
print(arr)
 """
(3)随机数组
np.random

方法

描述

random()

创建一维数组。参数为int(一维)或元组(生成数组形状),范围:[0,1)

rand()

创建均匀分布的随机数组。范围:[0,1)。在大量数据中可以观测到在各个子区间的均匀分布,少量数据观测不到。

randn()

创建服从正态分布的随机数组。均值为0,标准差为1。

randint(low,high,size)

范围:[low,high)。size:接收元组或列表,表示数组形状;整数表示一维数组元素个数。

seed()

产生的随机数为伪随机数。

# (1)创建n个在0~1之间的随机数,为一维数组
arr13 = np.random.random(10)
print(arr13)
# (2)创建服从均匀分布的随机数组
# arr14 = np.random.rand(1000)
arr14 = np.random.rand(3,4)	# 行列值
print(arr14)
# (3)创建服从正态分布的随机数组
arr15 = np.random.randn(100)
print(arr15)
# (4)创建随机整数的随机数组(左闭右开)
# arr16 = np.random.randint(2,22,size=6)
arr16 = np.random.randint(2,22,size=[3,4])
print(arr16)
4. 数组的属性

属性名称

属性介绍

shape

数组的结构,返回元组。

ndim

数组的维度,返回整数。

size

数组的元素个数。

dtype

数组的元素类型。

itemsize

元素的字节数。

5. 数组的索引
(1)一维数组的索引(切片)

与列表相同。

arr1 = np.array([1, 2, 3, 4])
print(arr1[::-1])	# [4, 3, 2, 1]
(2)二维数组的切片

arr[行切片, 列切片]

arr2 = np.array([[1, 2, 3], [0, 1, 2], [2, 3, 1]])
print("arr2:",arr2)
print("arr2[1,2]:",arr2[1,2])
print("arr2[1,:2]:",arr2[1,:2])
print("arr2[:2,0:2]:",arr2[:2,0:2])
"""
arr2: [[1 2 3]
 [0 1 2]
 [2 3 1]]
arr2[1,2]: 2
arr2[1,:2]: [0 1]
arr2[:2,0:2]: [[1 2]
 [0 1]]
"""
(3)二维数组索引元组

针对不同行不同列的取值。
arr[(行索引),(列索引)]

arr2[(0,1,1),(1,0,2)]	# [2, 0, 2]
(4)bool取值

注:不要行列同时传入布尔值。同时传值方式为第三种元组取值。只在行的位置或列的位置传入即可。

mask = np.array([1,0,1],dtype=np.bool)
print(mask)				# [True False True]
print(arr2[mask,:2])	# [[1,2] [2,3]]
print(arr2[:2,mask])	# [[1,3] [0,2]]
print(arr2[mask,mask])	# [1,1]	尽量避免,不推荐
6.数组的结构重置
(1)一维变二维

方法

描述

reshape

对已定形状数组的更改。参数是元组,指定修改后的数组形状。

arr_1 = np.arange(10)
print(arr_1)    # [0 1 2 3 4 5 6 7 8 9]
arr_2 = arr_1.reshape((2,5))
print(arr_2)
"""
[[0 1 2 3 4]
 [5 6 7 8 9]]
"""

注意:

  • reshape要保证更改前后元素个数相同,否则报错。
  • reshape((-1,1)):将数组转化为二维一列的数组,不管有多少行,-1只是占位作用。
(2)展平(二维变一维)

方法

描述

ravel()

自动拼接在前一行的后面。默认按行拼接。

flatten()

自动拼接在前一行的后面。默认按行拼接。

可以通过order参数指定展平方式。order=‘C’:横向展平;order=‘F’:纵向展平

# 展平方法一:ravel
print(arr_2.ravel())    # [0 1 2 3 4 5 6 7 8 9]
# 展平方法二:flatten
print(arr_2.flatten('C'))   # [0 1 2 3 4 5 6 7 8 9]
print(arr_2.flatten('F'))   # [0 5 1 6 2 7 3 8 4 9]

区别:当按行展开时,flatten是对原数组copy一份,修改展开的数组,不影响原数组的元素值。ravel对展开数组修改,原数组的元素值同时被修改,按列展开没有差别。

(3)合并

方法

描述

hstack((arr1,arr2,…,arrn))

水平合并,保证行数相同。

vstack((arr1,arr2,…,arrn))

垂直合并,保证列数相同。

concatenate((arr1,arr2,…,arrn),axis=0)

默认水平合并,可以通过axis参数指定方向。

区别

  • concatenate是严格按照数组轴的方向拼接的,一维数组只有一个0轴,所以只能横向合并。对于二维数组来说,axis=0为纵向合并,axis=1为横向合并。
  • hstack/vstack不关注有几个轴,只要行列数保持一致就可以进行合并,一维数组只要列数与另一个数组相同就可以进行纵向合并。
arr_3 = np.zeros((3,4))
arr_4 = np.ones((3,4))
arr_5 = np.eye(3)
# 横向堆叠(保证行数相同)
arr_heng = np.hstack((arr_3,arr_4,arr_5))
print(arr_heng)
"""
[[0. 0. 0. 0. 1. 1. 1. 1. 1. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 0. 1. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 0. 0. 1.]]
"""
# 纵向堆叠(保证列数相同)
arr_zong = np.vstack((arr_3,arr_4))
print(arr_zong)
"""
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]]
"""

# 数组合并
# 纵向合并 axis=0
print(np.concatenate((arr_3, arr_4), axis=0))
"""
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]]
"""
# 横向合并 axis=1(一维数组横向合并axis=0)
print(np.concatenate((arr_4, arr_3, arr_4), axis=1))
"""
[[1. 1. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1.]
 [1. 1. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1.]
 [1. 1. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1.]]
"""

# 一维数组的合并
ar_1 = np.array([1,2,3,4])
ar_2 = np.array([5,6,7,8])
# 一维数组只能横向合并
print(np.concatenate((ar_1, ar_2), axis=0)) # [1 2 3 4 5 6 7 8]
# print(np.concatenate((ar_1, ar_2), axis=1)) # 报错
print(np.concatenate((ar_1, arr_3), axis=1)) # 报错
# 横向堆叠
print(np.hstack((ar_1, ar_2)))  # [1 2 3 4 5 6 7 8]
# 纵向堆叠,一维可以和二维堆叠
print(np.vstack((ar_1, arr_3)))
"""
[[1. 2. 3. 4.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
"""
print(np.vstack((ar_1, arr_3)))
"""
[[1. 2. 3. 4.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
"""
(4)分割

方法

描述

hsplit()

横向分割列,行数不变。

vstack()

纵向分割行,列数不变。

split(arr,n,axis=0)

按轴分割。axis=0:切割行;axis=1:切割列。

arr_3 = np.zeros((3,4))
arr_4 = np.ones((3,4))
arr_heng = np.hstack((arr_3,arr_4)) # 三行八列
# 横向分割,分割列,行数不变
print(np.hsplit(arr_heng, 4))   # 按列分割成四个
"""
[array([[0., 0.],
       [0., 0.],
       [0., 0.]]), array([[0., 0.],
       [0., 0.],
       [0., 0.]]), array([[1., 1.],
       [1., 1.],
       [1., 1.]]), array([[1., 1.],
       [1., 1.],
       [1., 1.]])]
"""
# 任意分割(按索引分割列)
# 分割成4,2,1,1列
print(np.hsplit(arr_heng, [4, 6, 7]))
"""
[array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]]), array([[1., 1.],
       [1., 1.],
       [1., 1.]]), array([[1.],
       [1.],
       [1.]]), array([[1.],
       [1.],
       [1.]])]
"""
print(np.hsplit(arr_heng, [4, 6, 7, 8]))
"""
写上8会多出一个空数组,因为取不到
[array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]]), array([[1., 1.],
       [1., 1.],
       [1., 1.]]), array([[1.],
       [1.],
       [1.]]), array([[1.],
       [1.],
       [1.]]), array([], shape=(3, 0), dtype=float64)]
"""

# 纵向分割(分割行,列数不变)
arr_zong = np.vstack((arr_3,arr_4))
print(np.vsplit(arr_zong, 3))
"""
[array([[0., 0., 0., 0.],
       [0., 0., 0., 0.]]), array([[0., 0., 0., 0.],
       [1., 1., 1., 1.]]), array([[1., 1., 1., 1.],
       [1., 1., 1., 1.]])]
"""

# 按轴分割 axis=0:切割行,列数不变  axis=1:切割列,行数不变
print(np.split(arr_zong, 3, axis=0))
"""
[array([[0., 0., 0., 0.],
       [0., 0., 0., 0.]]), array([[0., 0., 0., 0.],
       [1., 1., 1., 1.]]), array([[1., 1., 1., 1.],
       [1., 1., 1., 1.]])]
"""
print(np.split(arr_heng, 4, axis=1))
"""
[array([[0., 0.],
       [0., 0.],
       [0., 0.]]), array([[0., 0.],
       [0., 0.],
       [0., 0.]]), array([[1., 1.],
       [1., 1.],
       [1., 1.]]), array([[1., 1.],
       [1., 1.],
       [1., 1.]])]
"""
7.数组的运算

数组的所有运算都是对应元素进行运算。数组的形状必须相同。

(1)四则运算

方法

描述

arr1+arr2

相加

arr1-arr2

相减

arr1*arr2

相乘

arr1/arr2

相除。零不能作除数。

arr1**arr2

幂运算

arr1%arr2

取模运算。零不能做除数。

arr1 = np.arange(1,17).reshape((4,4))
arr2 = np.diag([2,3,1,5])
# print(arr1+arr2)
# print(arr1-arr2)
# print(arr1*arr2)
# print(arr2/arr1)
# print(arr1**arr2)
# print(arr2%arr1)
(2)比较运算

返回一个数组,数组内元素类型为np.bool。数组可以与整数进行比较

方法

描述

arr1>arr2

arr1的元素是否大于arr2中的元素

arr1<arr2

arr1的元素是否小于arr2中的元素

arr1>=arr2

arr1的元素是否大于等于arr2中的元素

arr1<=arr2

arr1的元素是否小于等于arr2中的元素

arr1==arr2

arr1的元素是否等于arr2中的元素

arr1!=arr2

arr1的元素是否不等于arr2中的元素

arr1 = np.arange(1,17).reshape((4,4))
arr2 = np.diag([2,3,1,5])
# print(arr1<arr2)
"""
[[ True False False False]
 [False False False False]
 [False False False False]
 [False False False False]]
"""
mask = arr1<9
# print(mask)
"""
[[ True  True  True  True]
 [ True  True  True  True]
 [False False False False]
 [False False False False]]
"""
print(arr1[mask])   # [1 2 3 4 5 6 7 8]
(3)逻辑运算

方法

描述

all

逻辑与。返回一个布尔值。全部为True,结果才为True。

any

逻辑或。返回一个布尔值。全部为False,结果才为False。

# print(mask)
"""
[[ True  True  True  True]
 [ True  True  True  True]
 [False False False False]
 [False False False False]]
"""
print(np.all(mask)) # False
print(np.any(mask)) # True
(5)数组的广播

广播是指不同形状之间的数组之间执行算术运算的方式。

arr1 = np.arange(1,17).reshape((4,4))
# 二维数组+行向量
arr3 = np.array([2,5,9,4])
# print(arr1+arr3)
"""
[[ 3  7 12  8]
 [ 7 11 16 12]
 [11 15 20 16]
 [15 19 24 20]]
"""
# 二维数组+列向量
arr4 = np.array([[2],[5],[9],[4]])
# print(arr1+arr4)
"""
[[ 3  4  5  6]
 [10 11 12 13]
 [18 19 20 21]
 [17 18 19 20]]
"""
8.数组的特殊方法
(1)排序

方法

描述

sort

直接修改原数组,没有返回值。

argsort

返回一个数组,内部元素为排序后元素在原数组的索引

# sort:直接修改原数组,二维数组默认横向排列 axis=-1,axis=0为纵向排序
arr5 = np.array([21,10,20,18,15,1])
# arr5.sort()
# print(arr5) # [ 1 10 15 18 20 21]
# print(arr5.sort())  # None
# # argsort:返回一个数组对象,内部元素为排序后的索引,
# print(arr5.argsort())   # [5 1 4 3 2 0]
# print(type(arr5.argsort()))   # <class 'numpy.ndarray'>

arr6 = np.array([[12,2,10,9],[2,90,25,1]])
print("排序前:\n",arr6)
"""
排序前:
 [[12  2 10  9]
 [ 2 90 25  1]]
"""
# arr6.sort()
# print("每行排序后:\n",arr6)
"""
每行排序后:
 [[ 2  9 10 12]
 [ 1  2 25 90]]
"""
arr6.sort(axis=0)
print("每列排序后:\n",arr6)
"""
每列排序后:
 [[ 2  2 10  1]
 [12 90 25  9]]
"""
print(arr6.argsort())
"""
[[3 0 1 2]
 [3 0 2 1]]
"""
(2)去重

方法

描述

unique(arr,axis=None,return_counts=False)

找出数组中的唯一值,并返回排序后的数组。

  • 可指定轴判断,将行列看成一个整体。axis=0:整行相同去重;axis=1:整列相同去重。
  • return_counts:为True时可返回每个唯一项出现在arr中的次数。
  • 应用场景:
    统计类别种类数目;
    信息清洗、去重,例如班级学员统计,可以根据学号、手机号去重。
# 去重:返回一个去重排序后的一维数组
arr = np.array([21,2,21,1,0,1])
print(np.unique(arr))   # [ 0  1  2 21]
arr2 = np.array([[1,2,3,1],[0,2,3,0]])
print(np.unique(arr2))  # [0 1 2 3]
# 指定轴判断,将行、列看成一个整体
arr3 = np.array([[1,2,1,2],[1,2,1,2]])
print(np.unique(arr3,axis=0))   # [[1 2 1 2]]
arr4 = np.array([[1,2,1,2],[0,2,0,2]])
print(np.unique(arr4,axis=1))
"""
[[1 2]
 [0 2]]
"""
(3)重复

方法

描述

tile

对数组进行重复操作。可以指定重复次数和维度重复,默认按列的方向重复。

repeat

对数组元素进行重复操作。

# tile:以整个数组作为整体(元素) 进行重复,默认在列的方向上重复
arr1 = np.arange(4).reshape(2,2)
# print(arr1)
"""
[[0 1]
 [2 3]]
"""
# res = np.tile(arr1, 2)
"""
[[0 1 0 1]
 [2 3 2 3]]
"""
# res = np.tile(arr1, (2,2))
# print(res)
"""
[[0 1 0 1]
 [2 3 2 3]
 [0 1 0 1]
 [2 3 2 3]]
"""

# repeat:对数组元素的重复
# res = np.repeat(arr1, 2, axis=0)  # 在行的方向上数组元素重复
# res = np.repeat(arr1, 2, axis=1)  # 在列的方向上数组元素重复

# 如果不指定axis,将二维数组展平为一维,对每个元素进行重复指定次数
res = np.repeat(arr1, 2)
# print("重复后的数组\n", res)
"""
重复后的数组
 [0 0 1 1 2 2 3 3]
"""
9.数组的统计分析方法

方法

描述

max

数组的最大值

min

数组的最小值

argmax

数组的最大值索引(先展开再比较)

argmin

数组的最小值索引(先展开再比较)

std

数组的标准差

var

数组的方差

sum

数组的和

mean

数组的平均值

cumsum

数组中所有元素的累计和

cumprod

数组中所有元素的累计积

注意:当axis=0时,表示计算每一列;axis=1,计算每一行。默认是计算一个总值。

import numpy as np

arr1 = np.array([[1, 2, 45, 6], [2, 56, 4, 20], [45, 9, 20, 5]], dtype='int64')
# print(arr1)

# 1. 最大值
# print(f"数组中最大值 ---- {arr1.max()}")  # 数组中最大值 ---- 56
# print(f"数组每一行中最大值 ---- {arr1.max(axis=1)}")  # 数组每一行中最大值 ---- [45 56 45]
# print(f"数组每一列中最大值 ---- {arr1.max(axis=0)}")  # 数组每一列中最大值 ---- [45 56 45 20]

# 2. 最小值
# print(f"数组中最小值 ---- {arr1.min()}")  # 数组中最小值 ---- 1
# print(f"数组每一行中最小值 ---- {arr1.min(axis=1)}")  # 数组每一行中最小值 ---- [1 2 5]
# print(f"数组每一列中最小值 ---- {arr1.min(axis=0)}")  # 数组每一列中最小值 ---- [1 2 4 5]

# 3.最大值索引(先展平再比较)
# print(arr1.argmax())    # 5
# print(arr1.argmax(axis=1))  # [2 1 0]
# print(arr1.argmax(axis=0))  # [2 1 0 1]

# 4.最小值索引
# print(arr1.argmin())    # 0
# print(arr1.argmin(axis=1))  # [0 0 3]
# print(arr1.argmin(axis=0))  #[0 0 1 2]

# 5.标准差和方差
# 方差和标准差可以反映数据的分布,标准差与方差越小,数据越集中;反之,数据越分散。
# print(f"标准差 ---- {arr1.std()}") # 标准差 ---- 18.93171207847357
# print(f"每列标准差 ---- {arr1.std(axis=0)}") # 每列标准差 ---- [20.51016008 23.97684068 16.87206765  6.84754619]
# print(f"方差 ---- {arr1.var()}")  # 方差 ---- 358.4097222222221
# print(f"每行方差 ---- {arr1.var(axis=1)}")  # 每行方差 ---- [334.25   468.75   242.6875]

# 6.求和与平均值
# print(f"和 ---- {arr1.sum()}")   # 和 ---- 215
# print(f"每行的和 ---- {arr1.sum(axis=1)}")  # 每行的和 ---- [54 82 79]
# print(f"每列的和 ---- {arr1.sum(axis=0)}")  # 每列的和 ---- [48 67 69 31]
# print(f'平均值 ---- {arr1.mean()}')    # 平均值 ---- 17.916666666666668
# print(f'每行的平均值 ---- {arr1.mean(axis=1)}')   # 每行的平均值 ---- [13.5  20.5  19.75]
# print(f'每列的平均值 ---- {arr1.mean(axis=0)}')   # 每列的平均值 ---- [16.         22.33333333 23.         10.33333333]


# 7.累计求和
# print(f"累计求和 ---- {arr1.cumsum()}") # 累计求和 ---- [  1   3  48  54  56 112 116 136 181 190 210 215]

# 8.累计求积
# print(f"累计求积 ---- {arr1.cumprod()}")
"""
累计求积 ---- [   1       2           90          540         1080          60480       
            241920    4838400    217728000   1959552000    39191040000   195955200000]
"""