Python之Numpy使用详解

NumPy

NumPy 不仅仅是 Python 科学计算中使用最多的库,还是 SciPy,Pandas 等库的基础,它提供了更加高级有效的数据结构,是专门为科学计算而生的库。

NumPy 通常与 SciPy(Scientific Python)和 Matplotlib(绘图库)一起使用, 这种组合广泛用于替代 MatLab,是一个强大的科学计算环境,有助于我们通过 Python 学习数据科学或者机器学习。

ndarray 对象

NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。

ndarray 内部组成

  • 一个指向数据(内存或内存映射文件中的一块数据)的指针

  • 数据类型或 dtype,描述在数组中固定大小值的格子

  • 一个表示数组形状(shape)的元组,表示各维度大小的元组

  • 一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要”跨过“的字节数

以上的概念,你可以在后面的学习中慢慢体会。

创建一个 ndarray 只需要调用 NumPy 的 array 函数即可

import numpy as np
a = np.array([1, 2, 2])
b = np.array([[1, 2], [5, 5], [7, 8]])
b[1,1]=10
print(a.shape)
print(b.shape)
print(a.dtype)
print(b)
>>>
(3,)
(3, 2)
int32
[[ 1  2]
 [ 5 10]
 [ 7  8]]

引用 numpy 库,调用 array 函数即可创建 ndarray。
创建一维数组只需要传入一个 list,创建多维数组,需要先把一个数组作为一个元素嵌套起来,再放入另一个数组当中。
提取 array 中的元素,可以使用切片的操作,b[1,1]。
使用 shape 属性来获取数组的形状(大小),如 b 数组为一个三行两列的数组。
使用 dtype 属性来获取数组中的数据类型。

数据类型

NumPy 支持的数据类型比 Python 内置的类型要多,下面罗列了一些常见类型

名称描述
bool_布尔型数据类型(True 或者 False)
int_默认的整数类型
int32整数(-2147483648 to 2147483647)
uint32无符号整数(0 to 4294967295)
float32单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位

数据类型对象(dtype)

数据类型对象可以用来创建符合我们期望数据结构的数组

numpy.dtype(object, align, copy)
  • object:要转换的数据类型对象

  • align:如果为 True,填充字段使其类似 C 的结构体

  • copy:复制 dtype 对象,如果为 False,则是对内置数据类型对象的引用

使用 dtype 创建结构数组

mydtype = np.dtype({
        'names': ['name', 'age', 'sex'],
        'formats': ['S32', 'i4', 'S32']
    })
persons = np.array([
            ('zhangsan', 20, 'man'),
            ('lisi', 18, 'woman'),
            ('wangwu', 30, 'man')
        ],
        dtype=mydtype)
print(persons)
>>>
[(b'zhangsan', 20, b'man') (b'lisi', 18, b'woman') (b'wangwu', 30, b'man')]

首先通过 dtype 函数定义一个结构类型,然后再使用 array 函数构建数组,dtype 参数使用我们定义的即可。

数组属性

NumPy 数组的维数称为秩(rank),一维数组的秩为 1,二维数组的秩为 2,以此类推。

在 NumPy 中,每一个线性的数组称为是一个轴(axis),也就是维度(dimensions)。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴(axis),第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维数。

很多时候可以声明 axis。axis=0,表示沿着第 0 轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作。

下面罗列了比较重要的 ndarray 对象属性

属性说明
ndim秩,即轴的数量或维度的数量
shape数组的维度
size数组元素的总个数
dtype元素的类型
itemsize每个元素的大小,以字节为单位

创建特殊数组

空数组

x = np.empty([3,2], dtype=int) 
print(x)
>>>
[[0 0]
 [0 0]
 [0 0]]

numpy.empty 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组

0 数组

zero1 = np.zeros(5)
zero2 = np.zeros(4, dtype=int)
print(zero1)
print(zero2)
>>>
[0. 0. 0. 0. 0.]
[0 0 0 0]

1 数组

one1 = np.ones(3)
one2 = np.ones(4, dtype=float)
print(one1)
print(one2)
>>>
[1. 1. 1.]
[1. 1. 1. 1.]

从已有数组创建数组

numpy.asarray,从列表,元组,多维数组创建数组

list1 = [1, 3, 5]
tuple1 = (1, 2, 3)
one = np.ones((2,3), dtype=int)
array1 = np.asarray(list1)
array2 = np.asarray(tuple1)
array3 = np.asarray(one)
print(array1)
print(array2)
print(array3)
>>>
[1 3 5]
[1 2 3]
[[1 1 1]
 [1 1 1]]

numpy.frombuffer,以流的形式读入转化成数组

str1 = b"Hello world"
buffer1 = np.frombuffer(str1, dtype='S1')
print(buffer1)
>>>
[b'H' b'e' b'l' b'l' b'o' b' ' b'w' b'o' b'r' b'l' b'd']

numpy.fromiter,可以从可迭代对象中建立数组

range1 = range(5)
iter1 = np.fromiter(range1, dtype=int)
print(iter1)
>>>
[0 1 2 3 4]

numpy.arange,从数值范围创建数组

myarray1 = np.arange(5)
print(myarray1)
>>>
[0 1 2 3 4]

numpy.linspace,建立一个等差数列的数组

myarray2 = np.linspace(1,9,5)
print(myarray2)
>>>
[1. 3. 5. 7. 9.]

数组操作

切片和索引

ndarray 对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。

ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。
a = np.arange(10)
print(a)
s = slice(2,7,2)   # 从索引 2 开始到索引 7 停止,间隔为2
print (a[s])
>>>
[0 1 2 3 4 5 6 7 8 9]
[2 4 6]

也可以使用冒号(:)来做切片

a = np.arange(10)
print(a)
b = a[2:7:2]   # 从索引 2 开始到索引 7 停止,间隔为 2
print(b)
>>>
[0 1 2 3 4 5 6 7 8 9]
[2 4 6]

修改数组形状

nunpy.reshape,可以在不改变数据的条件下修改数组形状

a = np.arange(6)
print("原始数组:", a)
b = a.reshape(3, 2)
print("变换后数组:", b)
>>>
原始数组: [0 1 2 3 4 5]
变换后数组: [[0 1]
 [2 3]
 [4 5]]

numpy.ndarray.flat,是一个数组元素迭代器,可以依次处理每个元素

a = np.arange(9).reshape(3,3) 
print ('原始数组:')
for row in a:
    print (row)

#对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器:
print ('迭代后的数组:')
for element in a.flat:
    print (element)
>>>
原始数组:
[0 1 2]
[3 4 5]
[6 7 8]
迭代后的数组:
0
1
2
3
4
5
6
7
8

翻转数组

numpy.transpose,可以对换数组的维度

a = np.arange(10).reshape(2, 5)
print(a)
b = a.transpose()
print(b)
>>>
[[0 1 2 3 4]
 [5 6 7 8 9]]
[[0 5]
 [1 6]
 [2 7]
 [3 8]
 [4 9]]

连接数组

numpy.concatenate,用于连接相同形状的两个或多个数组

a = np.array([[1,2],[3,4]])

print ('第一个数组:')
print (a)b = np.array([[5,6],[7,8]])

print ('第二个数组:')
print (b)# 两个数组的维度相同

print ('沿轴 0 连接两个数组:')
print (np.concatenate((a,b)))

print ('沿轴 1 连接两个数组:')
print (np.concatenate((a,b),axis = 1))
>>>
第一个数组:
[[1 2]
 [3 4]]
第二个数组:
[[5 6]
 [7 8]]
沿轴 0 连接两个数组:
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
沿轴 1 连接两个数组:
[[1 2 5 6]
 [3 4 7 8]]

分割数组

numpy.split,可以将数组分割为子数组

a = np.arange(9)

print ('第一个数组:')
print (a)

print ('将数组分为三个大小相等的子数组:')
b = np.split(a,3)
print (b)

print ('将数组在一维数组中表明的位置分割:')
b = np.split(a,[4,7])
print (b)
>>>
第一个数组:
[0 1 2 3 4 5 6 7 8]将数组分为三个大小相等的子数组:
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]将数组在一维数组中表明的位置分割:
[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]

另外还有对于数组元素的添加与删除操作

函数描述
resize返回指定形式的新数组
append将值添加到数组末尾
insert延指定轴将数值插入到指定下标之前
delete删掉某个轴的子数组,返回删除后的新数组
unique查找数组内的唯一元素

NumPy 统计运算

计算最大最小值

numpy.amin(),计算数组中延指定轴的最小值

numpy.amax(),计算数组中延指定轴的最大值

a = np.array([[3,7,5],[8,4,3],[2,4,9]])  
print ('数组是:')
print (a)
print ('调用 amin() 函数:')
print (np.amin(a,1))
print ('再次调用 amin() 函数:')
print (np.amin(a,0))
print ('调用 amax() 函数:')
print (np.amax(a))
print ('再次调用 amax() 函数:')
print (np.amax(a, axis =  0))
>>>
数组是:
[[3 7 5]
 [8 4 3]
 [2 4 9]]
调用 amin() 函数:
[3 3 2]
再次调用 amin() 函数:
[2 4 3]
调用 amax() 函数:
9
再次调用 amax() 函数:
[8 7 9]

不指定 axis 时,会在整个数组中查找最大或最小。
axis = 0,是对每一列进行操作,即把数组看成 [3, 8, 2],[7, 4, 4],[5, 3, 9],从中选出最大或最小
axis = 1,是对每一行进行操作,即把数组看成 [3, 7, 5],[8, 4, 3],[2, 4, 9]。

这里的 axis 不是很容易理解,还希望你能在这里多花费些时间,去实践,去领悟。

numpy.ptp,可以计算数组元素中最大值与最小值之差

a = np.array([[3,7,5],[8,4,3],[2,4,9]])  
print ('我们的数组是:')
print (a)
print ('调用 ptp() 函数:')
print (np.ptp(a))
print ('沿轴 1 调用 ptp() 函数:')
print (np.ptp(a, axis =  1))
print ('沿轴 0 调用 ptp() 函数:')
print (np.ptp(a, axis =  0))
>>>
我们的数组是:
[[3 7 5]
 [8 4 3]
 [2 4 9]]
调用 ptp() 函数:
7
沿轴 1 调用 ptp() 函数:
[4 5 7]
沿轴 0 调用 ptp() 函数:
[6 3 6]

numpy.percentile,计算百分位数,表示小于这个值的观察值的百分比

理解百分位数:第 p 个百分位数表示,它使得至少有 p% 的数据项小于等于这个值,且至少有 (100 - p)% 的数据项大于等于这个值。

例如:某个同学语文考试分数为 80,如果这个分数正好位于所有学生成绩的第 80 百分位数,那么即可知该成绩大于约 80% 人,约 20% 人的成绩高于该同学。

a = np.array([[10, 7, 4], [3, 2, 1]])
print ('数组是:')
print (a)

print ('调用 percentile() 函数:')
# 50% 的分位数,就是 a 里排序之后的中位数
print (np.percentile(a, 50)) 

# axis 为 0,在纵列上求
print (np.percentile(a, 50, axis=0)) 

# axis 为 1,在横行上求
print (np.percentile(a, 50, axis=1)) 

# 保持维度不变
print (np.percentile(a, 50, axis=1, keepdims=True))
>>>
数组是:
[[10  7  4]
 [ 3  2  1]]
调用 percentile() 函数:
3.5
[6.5 4.5 2.5]
[7. 2.]
[[7.]
 [2.]]

numpy.median,计算数组元素的中位数

a = np.array([[10, 7, 4], [3, 2, 1]])
print ('数组是:')
print (a)
print(np.median(a))
>>>
3.5

可以看出,percentile 中 p 等于 50 时,就是中位数

numpy.mean,平均数

a = np.array([[10, 7, 4], [3, 2, 1]])
print ('数组是:')
print (a)
print(np.mean(a))
>>>
4.5

numpy.average,计算加权平均值

a = np.array([1,2,3,4])
print ('数组是:')
print (a)
print ('调用 average() 函数:')
print (np.average(a))
wts = np.array([4,3,2,1])
print ('再次调用 average() 函数:')
print (np.average(a,weights = wts))
>>>
数组是:
[1 2 3 4]
调用 average() 函数:
2.5
再次调用 average() 函数:
2.0

标准差和方差

标准差是一组数据平均值分散程度的一种度量,是方差的算术平方根。

方差是每个样本值与全体样本值的平均数之差的平方值的平均数。

print (np.std([1,2,3,4]))
print (np.var([1,2,3,4]))
>>>
1.118033988749895
1.25

NumPy 排序

在 numpy 中排序一行代码就可以完成,直接调用 sort 函数即可。

numpy.sort(a, axis, kind, order)

默认情况下,使用的是快速排序算法;在 kind 里,可以指定 quicksort、mergesort 和 heapsort,分别表示快速排序、合并排序和堆排序;axis 默认是 -1,沿着最后的轴排序, axis=0 按列排序,axis=1 按行排序;对于 order 字段,如果数值包含字段,可以填写要排序的字段。

a = np.array([[3,7],[9,1]])  
print ('数组是:')
print (a)
print ('调用 sort() 函数:')
print (np.sort(a))
print ('按列排序:')
print (np.sort(a, axis =  0))
print ('按行排序:')
print (np.sort(a, axis =  1))
>>>
数组是:
[[3 7]
 [9 1]]
调用 sort() 函数:
[[3 7]
 [1 9]]
按列排序:
[[3 1]
 [9 7]]
按行排序:
[[3 7]
 [1 9]]
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

缓下脚步

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值