numpy中ndarray使用

numpy中ndarray使用

为什么使用ndarray

在Python中使用list列表可以非常灵活的处理多个元素的操作,但是其效率却比较低。ndarray数组相比于Python中的list列表具有以下特点:

ndarray数组中所有元素的数据类型是相同的,数据地址是连续的,批量操作数组元素时速度更快;list列表中元素的数据类型可以不同,需要通过寻址方式找到下一个元素

ndarray数组中实现了比较成熟的广播机制,矩阵运算时不需要写for循环

Numpy底层是用c语言编写的,内置了并行计算功能,运行速度高于纯Python代码

ndarray数组可以独立完成相加计算

# 使用numpy中的ndarray完成两个ndarray相加
import numpy as np
a = np.array([1, 2, 3, 4, 5])
b = np.array([2, 3, 4, 5, 6])
c = a + b 

打印C的结果可以看到

[ 3,  5,  7,  9, 11]

区别于列表相加使用for循环

ndarray数组的广播机制

按一定规则自动对数组的维度进行扩展以完成计算,如下面例子所示,1维数组和2维数组进行相加操作,ndarray数组会自动扩展1维数组的维度,然后再对每个位置的元素分别相加。

# 自动广播机制,1维数组和2维数组相加

# 二维数组维度 2x5
# array([[ 1,  2,  3,  4,  5],
#         [ 6,  7,  8,  9, 10]])
d = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
# c是一维数组,维度5
# array([ 4,  6,  8, 10, 12])
c = np.array([ 4,  6,  8, 10, 12])
e = d + c

打印结果为

[[ 5,  8, 11, 14, 17],
       [10, 13, 16, 19, 22]]

创建ndarray数组

有如下几种方式创建ndarray数组

从list列表创建

指定起止范围及间隔创建

创建值全为0的ndarray数组

创建值全为1的ndarray数组

# 从list创建array
a = [1,2,3,4,5,6]
b = np.array(a)`在这里插入代码片`

# 通过np.arange创建
# 通过指定start, stop (不包括stop),interval来产生一个1为的ndarray
a = np.arange(0, 20, 2)

# 创建全0的ndarray
a = np.zeros([3,3])

# 创建全1的ndarray
a = np.ones([3,3])

查看ndarray数组的属性

ndarray的属性包括形状shape、数据类型dtype、元素个数size和维度ndim等,下面的程序展示如何查看这些属性

# 数组的数据类型 ndarray.dtype
# 数组的形状 ndarray.shape,1维数组(N, ),二维数组(M, N),三维数组(M, N, K)
# 数组的维度大小,ndarray.ndim, 其大小等于ndarray.shape所包含元素的个数
# 数组中包含的元素个数 ndarray.size,其大小等于各个维度的长度的乘积

a = np.ones([3, 3])
print('a, dtype: {}, shape: {}, size: {}, ndim: {}'.format(a.dtype, a.shape, a.size, a.ndim))

结果为

a, dtype: float64, shape: (3, 3), size: 9, ndim: 2

改变ndarray数组的数据类型和形状

创建ndarray之后,可以对其数据类型进行更改,或者对形状进行调整,如下面的代码所示

# 转化数据类型
b = a.astype(np.int64)
print('b, dtype: {}, shape: {}'.format(b.dtype, b.shape))

# 改变形状
c = a.reshape([1, 9])
print('c, dtype: {}, shape: {}'.format(c.dtype, c.shape))

输出结果为

b, dtype: int64, shape: (3, 3)
c, dtype: float64, shape: (1, 9)

ndarray数组的基本运算

ndarray数组可以像普通的数值型变量一样进行加减乘除操作

标量和ndarray数组之间的运算

# 标量除以数组,用标量除以数组的每一个元素
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
1. / arr

# 标量乘以数组,用标量乘以数组的每一个元素
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
2.0 * arr

# 标量加上数组,用标量加上数组的每一个元素
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
2.0 + arr

# 标量减去数组,用标量减去数组的每一个元素
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
2.0 - arr

输出为

array([[1.        , 0.5       , 0.33333333],
       [0.25      , 0.2       , 0.16666667]])
array([[ 2.,  4.,  6.],
       [ 8., 10., 12.]])
array([[3., 4., 5.],
       [6., 7., 8.]])
array([[ 1.,  0., -1.],
       [-2., -3., -4.]])

两个ndarray数组之间的运算

# 数组 减去 数组, 用对应位置的元素相减
arr1 = np.array([[1., 2., 3.], [4., 5., 6.]])
arr2 = np.array([[11., 12., 13.], [21., 22., 23.]])
arr1 - arr2
# 数组 加上 数组, 用对应位置的元素相加
arr1 = np.array([[1., 2., 3.], [4., 5., 6.]])
arr2 = np.array([[11., 12., 13.], [21., 22., 23.]])
arr1 + arr2
# 数组 乘以 数组,用对应位置的元素相乘
arr1 * arr2
# 数组 除以 数组,用对应位置的元素相除
arr1 / arr2
# 数组开根号,将每个位置的元素都开根号
arr ** 0.5

ndarray数组的索引和切片

在程序中,通常需要访问或者修改ndarray数组某个位置的元素,也就是要用到ndarray数组的索引;有些情况下可能需要访问或者修改一些区域的元素,则需要使用数组的切片。索引和切片的使用方式与Python中的list类似,ndarray数组可以基于 -n ~ n-1 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。

# 1维数组索引和切片
a = np.arange(30)
a[10]
a = np.arange(30)
b = a[4:7]
b
#将一个标量值赋值给一个切片时,该值会自动传播到整个选区(如下图所示)
a = np.arange(30)
a[4:7] = 10
a
# 数组切片是原始数组的视图。这意味着数据不会被复制,
# 视图上的任何修改都会直接反映到源数组上
a = np.arange(30)
arr_slice = a[4:7]
arr_slice[0] = 100
a, arr_slice
# 通过copy给新数组创建不同的内存空间
a = np.arange(30)
arr_slice = a[4:7]
arr_slice = np.copy(arr_slice)
arr_slice[0] = 100
a, arr_slice
# 多维数组索引和切片
a = np.arange(30)
arr3d = a.reshape(5, 3, 2)
arr3d
# 只有一个索引指标时,会在第0维上索引,后面的维度保持不变
arr3d[0]
# 两个索引指标
arr3d[0][1]
# 两个索引指标
arr3d[0, 1]

# 结合上面列出的for语句的用法
# 使用for语句对数组进行切片
# 下面的代码会生成多个切片构成的list
# k in range(0, 6, 2) 决定了k的取值可以是0, 2, 4
# 产生的list的包含三个切片
# 第一个元素是a[0 : 0+2],
# 第二个元素是a[2 : 2+2],
# 第三个元素是a[4 : 4+2]
slices = [a[k:k+2] for k in range(0, 6, 2)]
slices

ndarray数组的统计运算

# 计算均值,使用arr.mean() 或 np.mean(arr),二者是等价的
arr = np.array([[1,2,3], [4,5,6], [7,8,9]])
arr.mean(), np.mean(arr)
# 求和
arr.sum(), np.sum(arr)
# 求最大值
arr.max(), np.max(arr)
# 求最小值
arr.min(), np.min(arr)
# 指定计算的维度
# 沿着第1维求平均,也就是将[1, 2, 3]取平均等于2,[4, 5, 6]取平均等于5,[7, 8, 9]取平均等于8
arr.mean(axis = 1)
# 沿着第0维求和,也就是将[1, 4, 7]求和等于12,[2, 5, 8]求和等于15,[3, 6, 9]求和等于18
arr.sum(axis=0)
# 沿着第0维求最大值,也就是将[1, 4, 7]求最大值等于7,[2, 5, 8]求最大值等于8,[3, 6, 9]求最大值等于9
arr.max(axis=0)
# 沿着第1维求最小值,也就是将[1, 2, 3]求最小值等于1,[4, 5, 6]求最小值等于4,[7, 8, 9]求最小值等于7
arr.min(axis=1)
# 计算标准差
arr.std()
# 计算方差
arr.var()
# 找出最大元素的索引
arr.argmax(), arr.argmax(axis=0), arr.argmax(axis=1)
# 找出最小元素的索引
arr.argmin(), arr.argmin(axis=0), arr.argmin(axis=1)

随机数np.random

创建随机ndarray数组

# 生成均匀分布随机数,随机数取值范围在[0, 1)之间
a = np.random.rand(3, 3)
# 生成均匀分布随机数,指定随机数取值范围和数组形状
a = np.random.uniform(low = -1.0, high = 1.0, size=(2,2))
# 生成标准正态分布随机数
a = np.random.randn(3, 3)
# 生成正态分布随机数,指定均值loc和方差scale
a = np.random.normal(loc = 1.0, scale = 1.0, size = (3,3))

设置随机数种子

# 可以多次运行,观察程序输出结果是否一致
# 如果不设置随机数种子,观察多次运行输出结果是否一致
np.random.seed(10)
a = np.random.rand(3, 3)
# 生成一维数组
a = np.arange(0, 30)
# 打乱一维数组顺序
print('before random shuffle: ', a)
np.random.shuffle(a)
print('after random shuffle: ', a)
# 生成一维数组
a = np.arange(0, 30)
# 将一维数组转化成2维数组
a = a.reshape(10, 3)
# 打乱一维数组顺序
print('before random shuffle: \n{}'.format(a))
np.random.shuffle(a)
print('after random shuffle: \n{}'.format(a))

随机打乱1维数组顺序时,发现所有元素位置都改变了;随机打乱二维数组顺序时,发现只有第行的顺序被打乱了,列的顺序保持不变。

随机选取元素

# 随机选取一选部分元素
a = np.arange(30)
b = np.random.choice(a, size=5)
发布了7 篇原创文章 · 获赞 4 · 访问量 446
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览