NumPy 通用函数(ufunc)的实现
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1 数学运算类 ufunc</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">1.1 指数函数:np.exp()</a></li><li><a href="#_lab2_0_1">1.2 平方根函数:np.sqrt()</a></li><li><a href="#_lab2_0_2">1.3 加法函数:np.add()</a></li></ul><li><a href="#_label1">2 统计与聚合类 ufunc</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_3">2.1 最大值函数:np.max()</a></li><li><a href="#_lab2_1_4">2.2 最小值函数:np.min()</a></li><li><a href="#_lab2_1_5">2.3 求和函数:np.sum()</a></li><li><a href="#_lab2_1_6">2.4 均值函数:np.mean()</a></li></ul><li><a href="#_label2">3 数组操作类 ufunc</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_7">3.1 排序函数:np.sort()</a></li><li><a href="#_lab2_2_8">3.2 索引排序函数:np.argsort()</a></li><li><a href="#_lab2_2_9">3.3 非零元素查找:np.nonzero()</a></li></ul><li><a href="#_label3">4 总结</a></li><ul class="second_class_ul"></ul></ul></div><p>NumPy 中的<strong>通用函数(ufunc)<strong>是一类对数组元素进行</strong>逐元素操作</strong>的函数,它们能高效地处理数组的数学运算、统计聚合与数组操作等任务,返回结果也是数组。下面我们针对常用的 ufunc 进行分类说明。</p><p class="maodian"><a name="_label0"></a></p><h2>1 数学运算类 ufunc</h2>
<p class="maodian"><a name="_lab2_0_0"></a></p><h3>1.1 指数函数:np.exp()</h3>
<p style="text-align:center">计算数组中每个元素的<strong>自然指数</strong>(即 <img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010809325848.png" />,其中 <img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010809325850.png" /> ≈ 2.71828)。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">import numpy as np
B = np.arange(3)# 创建数组
print("原始数组B:", B)
print("np.exp(B)的结果:", np.exp(B))# 输出</pre></div>
<p class="maodian"><a name="_lab2_0_1"></a></p><h3>1.2 平方根函数:np.sqrt()</h3>
<p>计算数组中每个元素的<strong>平方根</strong>。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">print("np.sqrt(B)的结果:", np.sqrt(B))# 输出</pre></div>
<p class="maodian"><a name="_lab2_0_2"></a></p><h3>1.3 加法函数:np.add()</h3>
<p>对两个数组执行<strong>逐元素加法</strong>运算。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">C = np.array()
print("原始数组C:", C)
print("np.add(B, C)的结果:", np.add(B, C))# 输出</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>2 统计与聚合类 ufunc</h2>
<p>这类函数用于对数组进行统计分析,如求极值、求和、求均值等。</p>
<p class="maodian"><a name="_lab2_1_3"></a></p><h3>2.1 最大值函数:np.max()</h3>
<p>返回数组中的最大值,也可通过数组方法 arr.max() 调用。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">arr = np.array()
print("数组最大值:", np.max(arr))# 输出5</pre></div>
<p class="maodian"><a name="_lab2_1_4"></a></p><h3>2.2 最小值函数:np.min()</h3>
<p>返回数组中的最小值,也可通过数组方法 arr.min() 调用。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">print("数组最小值:", np.min(arr))# 输出1</pre></div>
<p class="maodian"><a name="_lab2_1_5"></a></p><h3>2.3 求和函数:np.sum()</h3>
<p>计算数组所有元素的和,也可通过数组方法 arr.sum() 调用。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">print("数组元素和:", np.sum(arr))# 输出3+1+4+1+5=14</pre></div>
<p class="maodian"><a name="_lab2_1_6"></a></p><h3>2.4 均值函数:np.mean()</h3>
<p>计算数组元素的算术平均值,也可通过数组方法 arr.mean() 调用。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">print("数组均值:", np.mean(arr))# 输出14/5=2.8</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>3 数组操作类 ufunc</h2>
<p>这类函数用于对数组结构或元素顺序进行操作。</p>
<p class="maodian"><a name="_lab2_2_7"></a></p><h3>3.1 排序函数:np.sort()</h3>
<p>对数组元素进行<strong>排序</strong>(返回新数组,原数组不变)。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">arr = np.array()
sorted_arr = np.sort(arr)
print("排序后数组:", sorted_arr)# 输出</pre></div>
<p class="maodian"><a name="_lab2_2_8"></a></p><h3>3.2 索引排序函数:np.argsort()</h3>
<p>返回数组元素<strong>排序后的索引位置</strong>(即原数组中元素从小到大的位置编号)。</p>
<blockquote><p>【数组的索引】</p>
<p>在 NumPy 中,“索引” 是访问、修改或筛选数组元素的关键方式,其功能丰富且灵活。和 Python 列表类似,一维数组的索引从 0 开始,可通过整数索引获取单个元素,也能用切片(如arr)获取连续区间的元素;对于多维数组,需用逗号分隔的索引元组来指定维度,比如二维数组 arr 可通过 <strong>arr[行索引, 列索引]</strong> 精准定位元素,也能对某一维度单独切片(如 arr[:, 2] 获取所有行的第三列)。此外,布尔索引更是便捷,通过构造与原数组形状相同的布尔数组(如arr > 10),可直接筛选出满足条件的元素,这在数据清洗和分析中极为实用。简言之,索引机制让 NumPy 数组的元素操作既高效又灵活,是掌握 NumPy 数据处理能力的核心基础之一。</p></blockquote>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">indices = np.argsort(arr)
print("排序索引:", indices)# 输出,表示原数组第3个元素(1)最小,第1个元素(2)次之……</pre></div>
<p class="maodian"><a name="_lab2_2_9"></a></p><h3>3.3 非零元素查找:np.nonzero()</h3>
<p>返回数组中<strong>非零元素的索引</strong>。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;">arr = np.array()
nonzero_indices = np.nonzero(arr)
print("非零元素索引:", nonzero_indices)# 输出(array(),),表示第1、3个元素非零</pre></div>
<p>代码示例中,(array(),) 是 NumPy 中 np.nonzero() 函数返回的结果格式,本质是一个包含 1 个 NumPy 数组的元组。</p>
<p>其中,元组内的 array() 表示 “非零元素在数组中的索引位置”—— 比如当对一维数组 使用 np.nonzero() 时,数组中值不为 0 的元素(2 和 5)分别位于第 1 位和第 3 位(NumPy 索引从 0 开始),因此返回该索引数组;而外层的元组结构是为了适配多维数组场景:若处理的是二维数组,np.nonzero() 会返回包含两个数组的元组(分别对应非零元素的 “行索引” 和 “列索引”),即使是一维数组,也保持元组格式以保证接口一致性,末尾的逗号则是 Python 中单个元素元组的标准写法(避免与普通括号混淆)。</p>
<p>然而,这里的难点在于对于多维数组的情况。</p>
<p><strong>代码示例:</strong></p>
<div class="jb51code"><pre class="brush:py;"># 创建一个形状为(2, 3, 2)的三维数组
arr_3d = np.array([
[, , ],
[, , ]
])
nonzero_indices = np.nonzero(arr_3d)
print("非零元素的三维索引:", nonzero_indices)</pre></div>
<p>上述代码运行后会输出:</p>
<p><strong>非零元素的三维索引: (array(), array(), array()) </strong>。</p>
<p>我们可以对 arr_3d,逐个找出非零元素的位置,就能明白这个结果是怎么来的了。</p>
<p>arr_3d 的形状是 (2, 3, 2),可以理解为 “2 个深度层,每个深度层有 3 行、2 列”,具体结构如下:</p>
<div class="jb51code"><pre class="brush:py;"># 深度0的层(arr_3d):
[
,# 行0:列0是0,列1是1(非零)
,# 行1:列0是2(非零),列1是0
# 行2:列0是0,列1是3(非零)
]
# 深度1的层(arr_3d):
[
,# 行0:列0是4(非零),列1是0
,# 行1:列0是0,列1是5(非零)
# 行2:列0是6(非零),列1是0
]</pre></div>
<p>接下来,我们逐个找出所有非零元素,并记录它们的 “三维坐标”(深度索引,行索引,列索引):</p>
<blockquote><p>深度 0、行 0、列 1 的元素是 1(非零)→ 坐标 (0, 0, 1)<br />深度 0、行 1、列 0 的元素是 2(非零)→ 坐标 (0, 1, 0)<br />深度 0、行 2、列 1 的元素是 3(非零)→ 坐标 (0, 2, 1)<br />深度 1、行 0、列 0 的元素是 4(非零)→ 坐标 (1, 0, 0)<br />深度 1、行 1、列 1 的元素是 5(非零)→ 坐标 (1, 1, 1)<br />深度 1、行 2、列 0 的元素是 6(非零)→ 坐标 (1, 2, 0)</p></blockquote>
<p>现在,把这 6 个坐标按顺序拆分:</p>
<blockquote><p>所有坐标的 “深度索引” 提取出来:0, 0, 0, 1, 1, 1 → 组成第一个数组 array()<br />所有坐标的 “行索引” 提取出来:0, 1, 2, 0, 1, 2 → 组成第二个数组 array()<br />所有坐标的 “列索引” 提取出来:1, 0, 1, 0, 1, 0 → 组成第三个数组 array()</p></blockquote>
<p>这三个数组组合起来,就是 np.nonzero(arr_3d) 的返回结果,每个位置上的三个值对应一个非零元素的完整坐标。比如第 0 个位置的三个值 (0,0,1),就对应第一个非零元素 arr_3d = 1。</p>
<p class="maodian"><a name="_label3"></a></p><h2>4 总结</h2>
<p>NumPy 的通用函数(ufunc)是数组运算的核心工具,涵盖数学运算、统计分析、数组操作等多个场景。掌握这些常用 ufunc,能让你在数值计算中高效处理数组任务,为数据分析、科学计算等工作奠定基础。</p>
頁:
[1]