Numpy
作者:PureFFFmennory
对象类型:ndarry
上一节:4.2 快速创建数组
PureFFFmennory:《Python for Data Analysis 2nd》学习笔记Chapter 4-4.2zhuanlan.zhihu.com![303f9d5cbeb8d5b56bf966226616e925.png](https://i-blog.csdnimg.cn/blog_migrate/37fa5d940e4d4fc6e8ed4023bf2f6c2e.jpeg)
4.3 使用向量计算代替数组
使用Numpy数组,可以将许多类型的数据处理任务表达为简洁的数组表达式,从而免除了复杂的循环逻辑。该种数组表达式替换循环的做法通常被称为向量运算。通常,向量运算操作的速度比纯Python等效运算要快一到两(或更多)个数量级,在处理庞大的数据时,他们的差异是显著的。
作为一个简单的示例,假设我们希望在一个常值网格中计算$sqrt{x^2+y^2}$。np.meshgrid函数被传入用两个一维数组,并生成两个二维数组,对应于两个数组中的(x, y):
>> points = np.arange(-5, 5, 0.01) # 生成1000个等间距的点
>> xs, ys = np.meshgrid(points, points) # 生成两个二维网格
>> z = np.sqrt(xs ** 2, ys ** 2) # 计算函数表达式
我们利用matplotlib(后文将细述)创建该二维数组的可视化效果:
>> import matplotlib.pyplot as plt
>>
>> plt.imshow(z, cmap=plt.cm.gray)
>> plt.colorbar()
# 显示输出:<matplotlib.colorbar.Colorbar at 0x7f715e3fa630>
>> plt.title("Image plot of $sqrt{x^2 + y^2}$ for a grid of values")
# 显示输出:<matplotlib.text.Text at 0x7f715d2de748>
在这里,我使用matplotlib函数imshow从二维数组的函数值创建图像绘图。
![15b7e1e4c0bb367f016f3c7985753e4f.png](https://i-blog.csdnimg.cn/blog_migrate/1d4873f6ac0210394f07aeb884b79b30.jpeg)
将条件逻辑表示为数组操作
np.where函数是一个接受三个参数的函数,他可以将循环逻辑简化为数组操作,我们以例子说明,假定我们有一个布尔数组和两个数值数组:
>> xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
>> yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
>> cond = np.array([True, False, True, True, False])
假定我们现在希望当cond为True时,就取xarr中相应的元素,否则取yarr中相应的元素。执行此项功能的理解类似于:
>> result = [(x if c else y) for x, y, c in zip(xarr, yarr, cond)]
>> print(result)
# 输出:[1.1000000000000001, 2.2000000000000002, 1.3, 1.3999999999999999, 2.5]
这存在多个问题。首先,对于大型数组来说,它不是很快(因为所有工作都在解释型Python代码中完成)。其次,它不适用于多维数组,而有了np.where,你可以非常简洁的完成该功能:
>> result = np.where(cond, xarr, yarr)
>> print(result)
# 输出:array([ 1.1, 2.2, 1.3, 1.4, 2.5])
np.where的第二个和第三个参数不需要数组,其中一个或两个可以是数值标量。在数据分析中一个典型的用处是基于另一个数组生成新的值数组。假设你有一个随机生成的数据的矩阵,并且希望将所有的正值替换为2,所有的负值替换为-2。用np.where将非常容易完成这件事:
>> arr = np.random.randn(4, 4)
>> arr > 0
# 打印将输出一个布尔矩阵
>> np.where(arr > 0, 2, -2)
# 打印将输出一个数组,由2和-2构成,在原数组大于0的位置是2,小于0的位置是-2
使用np.where时,可以结合标量和数组。例如,我可以将arr中的所有正值替换为常量2,如下所示:
>> np.where(arr > 0, 2, arr)
# 打印将输出一个矩阵,在原矩阵大于0的地方都变为2
传递给np.where的数组可以不仅仅是大小相等的数组或标量。
数学和统计方法
计算有关整个数组或沿某一行或列的数据统计信息的一组数学函数可以作为数组类的方法访问。你可以通过调用数组实例方法或使用顶级Numpy函数来得到总和、均值和标准差等。
在这里,我生成一些正态分布的随机数据并计算一些统计信息:
>> arr = np.random.randn(5, 4)
>>
>> arr.mean()
>> np.mean(arr)
>> arr.sum()
mean和sum函数提供了一个关于轴向(行或列)的可选参数用于在给定轴上计算统计数值,生成低维的数组:
>> arr.mean(axis=1)
>> arr.sum(axis=0)
此处,arr.mean(1)表示“按列计算平均值”,其中arr.sum(0)表示“计算行的总和”。
其他方法如cumsum,cumprod不会求总和,而是生成一个累计数组,如:
>> arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])
>> arr.cumsum()
# 打印输出:array([ 0, 1, 3, 6, 10, 15, 21, 28])
我们发现,输出的数组的每一个值,是原数组对应位置前面所有数的总和。
对于多维数组来讲,累计函数(如cumsum)返回大小相同的数组,但根据每个低维切片沿指定轴计算局部总和:
>> arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
>> arr.cumsum(axis=0)
# 打印输出:([[ 0, 1, 2],
# [ 3, 5, 7],
# [ 9, 12, 15]])
>> arr.cumprod(axis=1)
# 打印输出:([[ 0, 0, 0],
# [ 3, 12,60],
# [ 6, 42, 336]])
有关完整列表参阅下表,我们将在后面的章节中看到这些方法的许多示例:
![d23f963fe69f5c0fee451dc3f69d3bae.png](https://i-blog.csdnimg.cn/blog_migrate/a64638c08664f4fab61df7b788e5afea.jpeg)
布尔数组方法
布尔值在上述方法中被强制为1(True)和0(False)。因此,sum通常是计算布尔数组中True值的方法:
>> arr = np.random.randn(100)
>> (arr > 0).sum() # 大于0的数量
# 打印输出:数组中大于0的元素的个数
有两种附加方法,any和all,特别适用于布尔数组。any检测数组中的一个值或多个值是否为True,而all检测每个值是否为True:
>> bools = np.array([False, False, True, False])
>> bools.any()
# 打印输出:True
>> bools.all()
# 打印输出:False
这些方法也适用于非布尔数组,其中非0元素均为True。
排序
与Python的内置列表一样,NumPy数组可以使用排序方法就地排序:
>> arr = np.random.randn(6)
>> arr.sort()
# 打印输出:从小到大排序的数组
你可以通过传递数组的轴向参数来排序,沿轴向对原多维数组在每一个位置进行排序:
>> arr = np.random.randn(5, 3)
>> arr.sort(1)
# 打印输出:将每一行从小到大进行排序
注意!顶级方法np.sort返回数组的排序副本,而不是就地修改数组。一个临时快速的计算数组的分位数(中位数、四分位数等)的方法是排序并选择特定排名的值:
>> large_arr = np.random.randn(1000) # 生成一千个数
>> large_arr.sort()
>> large_arr[int(0.05 * len(large_arr))] # 5%分位数
# 打印输出:输出排名第5%的数字
在Pandas中也可以找到与排序相关的几种其他类型的数据操作(例如,按一个或多个列对数据表进行排序)。
Unique和其他集合操作
NumPy具有一维ndarry的一些基本集合操作。常用的一个是np.unnique,它返回数组中排序的唯一的元素(即若数组中有重复的元素,就只返回一个,且将他们排序后输出):
>> names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
>> np.unique(names)
# 打印输出:array(['Bob', 'Joe', 'Will']), dtype='<U4’)
>> ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])
>> np.unique(ints)
# 打印输出:array([1, 2, 3, 4])
将纯Python语言与np.unique进行对比:
>> sorted(set(names))
# 打印输出:['Bob', 'Joe', 'Will']
另一个函数np.in1d,将检测一个数组的值的成员是否存在于另一个数组,返回布尔数组:
>> values = np.array([6, 0, 0, 3, 2, 5, 6])
>> np.in1d(values, [2, 3, 6])
# 打印输出:array([ True, False, False, True, True, False, True], dtype=boo;)
下面列出了一些NumPy中的集合函数:
![fe597b6058dc7a22016404934dfe8460.png](https://i-blog.csdnimg.cn/blog_migrate/245fd5630fe6065c7ab0e1c96815a23b.jpeg)
下一节:4.4 数组的文件输入与输出
PureFFFmennory:《Python for Data Analysis 2nd》学习笔记Chapter 4-4.4zhuanlan.zhihu.com![303f9d5cbeb8d5b56bf966226616e925.png](https://i-blog.csdnimg.cn/blog_migrate/37fa5d940e4d4fc6e8ed4023bf2f6c2e.jpeg)