虽然深入理解NumPy对于大部分数据分析应用并不是必需的,但是精通基于数组的编程和思考是成为Python科学计算专家的重要一步。本文将带你上手精通 NumPy!
1、生成 ndarray
生成数组最简单的方式就是使用 array 函数。array 函数接收任意的序列型对象(当然也包括其他的数组),生成一个新的包含传递数据的 NumPy 数组。如下将列表转为一维数组
import numpy as np
data = np.array([[1, 2, 3]])
data
# Output
# array([[1, 2, 3]])
当然我们也可以将二维列表转为二维数组
import numpy as np
data = np.array([[1, 2, 3],[4, 5, 6]])
data
# Output
# array([[1, 2, 3], [4, 5, 6]])
除了 np.array,还有很多其他函数可以创建新数组。例如,给定长度及形状后,zeros 可以一次性创造全0数组,使用 ones 可以一次性创造全1数组
import numpy as np
np.zeros(5)
# Output
# array([0., 0., 0., 0., 0.])
np.ones(5)
# Output
# array([1., 1., 1., 1., 1.])
同时可以使用 arange 生成等间隔数值序列,它的基本用法和参数如下:
numpy.arange([start], stop[, step], dtype=None)
- start(可选):序列的起始值,默认为 0。
- stop:序列的结束值(不包括该值)。
- step(可选):步长,默认为 1。表示每两个相邻值之间的差。
- dtype(可选):输出数组的数据类型。如果未指定,NumPy 会根据输入的值自动推断。
例子如下
import numpy as np
np.arange(2, 10, 2)
# Output
# array([2, 4, 6, 8])
2、ndarray 的数据类型
ndarray 中的数据类型用 dtype 表示,ndarray 需要为某一种类型数据所申明的内存块信息,numpy 会在数据初始化的时候根据初始的数据,推测数据类型
import numpy as np
data = np.array([[1, 2, 3],[4, 5, 6]])
data.dtype # dtype('int32')
我们也可以在初始化的时候,制定数据类型,如下所示
import numpy as np
data = np.array([[1, 2, 3],[4, 5, 6]], dtype=np.float64)
data.dtype # dtype('float64')
如果数组的类型不是我们想要的,我们可以使用 astype 方法显式地转换数组的数据类型
import numpy as np
arr = np.array([1, 2, 3]) # dtype('int32')
float_arr = arr.astype(np.float64)
float_arr.dtype # dtype('float64')
3、NumPy 数组算术
NumPy 数组之所以快有一个很重要的原因:它允许你进行批量操作而无须任何 for 循环,也即向量化!
任何在两个等尺寸数组之间的算术操作都应用了逐元素操作的方式,如下所示
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
arr * arr
# Output
# array([[ 1, 4, 9], [16, 25, 36]])
arr - arr
# Output
# array([[0, 0, 0], [0, 0, 0]])
带有标量计算的算术操作,会把计算参数传递给数组的每一个元素,如下所示
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
1 / arr
# Output
# array([[1. , 0.5, 0.33333333], [0.25, 0.2 , 0.16666667]])
同尺寸数组之间的比较,会产生一个布尔值数组,如下所示
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array([[6, 5, 4], [3, 2, 1]])
arr2 > arr
# Output
# array([[True, True, True], [ False, False, False]])
4、基础索引与切片
(1)数组的索引
可以使用数组的下标去获取单个元素的值,如下所示,有以下两种方式,其结果一样
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
arr[1,2] # 6
arr[1][2] # 6
(2)数组切片
我们可以通过数组切片获取数组的子集,区别于Python的内建列表,数组的切片是原数组的视图。这意味着数据并不是被复制了,任何对于视图的修改都会反映到原数组上
arr = np.arange(10)
arr[2:5]
# Output
# array([2, 3, 4])
# 修改
arr[2:5] = 10
arr
# Output
# array([ 0, 1, 10, 10, 10, 5, 6, 7, 8, 9])
不写切片值的 [:] 将会引用数组的所有值:
arr[:] = 10
arr
# Output
# array([10, 10, 10, 10, 10, 10, 10, 10, 10, 10])
Python 的这种视图的操作,主要是由于 NumPy 被设计成适合处理非常大的数组,你可以想象如果 NumPy 持续复制数据会引起多少内存问题。
如果你还是想要一份数组切片的拷贝而不是一份视图的话,你就必须显式地复制这个数组,例如arr[2:5].copy(),如下所示,copy 后的数组发生数值更改,但是原数组中的数值没有发生改变。
arr = np.arange(10)
arr_2 = arr[2:5].copy()
arr_2[:] = 10
arr
# Output
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
(3)多维数组的切片
NumPy 的多维数组切片功能非常强大,可以方便地访问和操作数组的特定部分,首先,我们可以创建一个多维数组(如二维数组)来进行切片操作:
import numpy as np
# 创建一个 3x4 的二维数组
arr = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
基本语法为 array[start:stop:step]
,其中 start
是起始索引,stop
是结束索引(不包括该索引),step
是步长
(3.1)切片单个维度
则访问特定行,如下所示
row = arr[1] # 访问第二行
row
# Output
# array([5, 6, 7, 8])
访问特定列,如下所示
column = arr[:, 2] # 访问第三列
column
# Output
# array([ 3, 7, 11])
(3.2)切片多个维度
访问特定子数组:
sub_array = arr[0:2, 1:3] # 访问前两行和第二、第三列
sub_array
# Output
# array([[2, 3],
# [6, 7]])
访问特定元素:
element = arr[2, 3] # 访问第三行第四列的元素
element # 12
(4)使用步长切片
每隔一行和一列
sliced = arr[::2, ::2] # 每隔一行和一列
sliced
# Output
# array([[ 1, 3],
# [ 9, 11]])
(5)布尔索引
可以使用布尔数组进行切片,选择满足特定条件的元素:
bool_index = arr > 5 # 创建布尔索引
filtered = arr[bool_index] # 选择大于 5 的元素
filtered
# Output
# array([ 6, 7, 8, 9, 10, 11, 12])
(6)花式索引
可以使用数组索引选择特定的行或列:
rows = np.array([0, 2])
cols = np.array([1, 3])
fancy_index = arr[rows, cols] # 选择 (0,1) 和 (2,3) 的元素
fancy_index
# Output
# array([ 2, 12])
5、数组的转置和换轴
(1)数组的转置
转置是指将数组的行和列互换。对于二维数组,转置操作将第一维(行)变为第二维(列),第二维变为第一维。我们可以使用 .T
属性进展转置
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6]])
arr.T
# Output
# array([[1, 4],
# [2, 5],
# [3, 6]])
除了 .T
属性,还可以使用 np.transpose()
函数进行转置。
np.transpose(arr)
# Output
# array([[1, 4],
# [2, 5],
# [3, 6]])
(2)数组的换轴
换轴是指在多维数组中交换任意两个轴的位置。对于高维数组,这种操作非常有用。我们可以使用 np.swapaxes()
,如下所示
arr_3d = np.random.rand(2, 3, 4)
# 交换第 0 轴和第 1 轴
swapped = np.swapaxes(arr_3d, 0, 1)
swapped.shape
# Output
# (3, 2, 4)
我们还可以使用 np.rollaxis()
,其可以将指定的轴移动到目标位置。
# 将第 0 轴移动到第 2 个位置
rolled = np.rollaxis(arr_3d, 0, 2)
rolled.shape
# Output
# (3, 4, 2)
6、通用函数:快速的逐元素数组函数
通用函数,也可以称为ufunc,是一种在ndarray数据中进行逐元素操作的函数。某些简单函数接收一个或多个标量数值,并产生一个或多个标量结果,而通用函数就是对这些简单函数的向量化封装。我们简单举两个例子如下
import numpy as np
arr = np.arange(10)
np.max(arr) # 9
np.sum(arr) # 45
以下为常用的通用函数,大家可以根据需要的时候选择使用
如果你喜欢本文,欢迎点赞,并且关注我们的微信公众号:Python技术极客,我们会持续更新分享 Python 开发编程、数据分析、数据挖掘、AI 人工智能、网络爬虫等技术文章!让大家在Python 技术领域持续精进提升,成为更好的自己!
添加作者微信(coder_0101),拉你进入行业技术交流群,进行技术交流~