️ NumPy 迭代
可以把迭代想象成“检阅士兵”。
- 迭代就是你走过去,一个一个(或者一队一队)地检查他们,或者给他们下达指令(比如修改数值)。
在 Python 原生列表里,习惯用 for 循环。但在 NumPy 中,虽然也可以用 for,但有更专业、更高效的“武器”。
1. 直接 for 循环
这是最基础的方法,适合简单的查看。
import numpy as npprint('直接 for 循环')# --- 一维数组 ---arr_1d = np.array([1, 2, 3])print("一维遍历:")for x in arr_1d:print(x) # 输出: 1, 2, 3# --- 二维数组 ---arr_2d = np.array([[1, 2, 3], [4, 5, 6]])print("\n二维遍历 (默认按行):")for row in arr_2d:print(row)# 输出: [1 2 3]# [4 5 6]
2. NumPy 的高效迭代器:np.nditer()
这是 NumPy 提供的专业工具,功能更强大。
① 逐元素遍历(自动拍扁)无论数组多少维,它都能将其视为一维进行遍历。
print('numpy的高效迭代器np.nditer()')arr = np.array([[1, 2], [3, 4]])print("使用 nditer 遍历 (自动拍扁):")for x in np.nditer(arr):print(x)# 输出: 1, 2, 3, 4
② 控制遍历顺序可以通过 order 参数指定遍历顺序(例如按列优先)。
print("\n使用 nditer 遍历 (按列优先 order='F'):")for x in np.nditer(arr, order='F'):print(x, end=' ')# 输出: 1 3 2 4 (先读第一列,再读第二列)print()
③ 修改数组元素默认情况下迭代器是只读的。如果需要修改,必须加上 op_flags=['readwrite'] 开启读写模式,并使用 x[...] 进行赋值。
# --- 修改数组元素 ---arr_modify = np.array([1, 2, 3])# 加上 op_flags=['readwrite'] 开启读写模式with np.nditer(arr_modify, op_flags=['readwrite']) as it:for x in it: x[...] = x * 10# 注意:要用 x[...] 才能修改原数组print("\n修改后的数组:", arr_modify) # 输出: [10 20 30]
3. 带着坐标跑:np.ndenumerate()
有时候不仅要拿数据,还要知道数据的位置(索引)。
print('-----------------')print('带着坐标跑:np.ndenumerate()')arr = np.array([[1, 2, 3], [4, 5, 6]])for index, value in np.ndenumerate(arr):print(f"索引: {index}, 数值: {value}")
️ 注意:NumPy 的核心哲学
虽然介绍了很多迭代的方法,但必须说明:在 NumPy 中,Python 层面的循环(for/while)通常是很慢的。
如果只是想对每个元素做同样的数学运算(比如全部乘以 2,全部开根号),千万不要用迭代,请直接使用向量化运算或广播。
总结
- 复杂遍历/修改:用
np.nditer()(记得加 op_flags)。 - 数学计算:别用迭代,直接用
arr * 2 这种向量化写法! 你觉得这个排版符合你的预期吗?需要我帮你把代码块里的中文注释翻译成英文,或者把总结部分做成表格形式以便对比吗?
NumPy 数组形状操作
在 NumPy 中,修改数组形状就像玩“橡皮泥”一样。你可以把一块泥巴捏成扁平的、细长的或者方块状的,只要泥巴的总量(元素个数)不变就行。
核心方法:reshape()核心规则:变换前后的元素总个数必须一致。
1. reshape() 的基础用法
import numpy as npprint('reshape()的基础用法')# 创建一个有 12 个元素的一维数组arr = np.arange(12)print("原始数组:", arr)# 输出: [ 0 1 2 3 4 5 6 7 8 9 10 11]# 把它变成 3 行 4 列new_arr = arr.reshape(3, 4)print("变形后:\n", new_arr)
** 偷懒技巧:使用 -1** 如果不想算某个维度具体是多少,可以用 -1 代替。NumPy 会自动帮你计算出来。
print('变成 4 行,列数自动计算:')auto_arr = arr.reshape(4, -1)print(auto_arr)# 输出: 4 行 3 列的数组
2. 视图 vs 副本:ravel() vs flatten()
这两个方法都是用来把多维数组“拍扁”成一维数组的,但它们有一个巨大的区别,也是面试常考点:一个是“影子”(视图),一个是“克隆”(副本)。
代码演示:
arr = np.array([[1, 2], [3, 4]])# --- 使用 ravel (视图) ---flat_r = arr.ravel()flat_r[0] = 999# 修改第一个元素print("修改 ravel 后的原数组:", arr)# 输出: [[999 2] [ 3 4]] <-- 原数组变了!# --- 使用 flatten (副本) ---arr = np.array([[1, 2], [3, 4]]) # 重置数组flat_f = arr.flatten()flat_f[0] = 888print("修改 flatten 后的原数组:", arr)# 输出: [[1 2] [3 4]] <-- 原数组没变!
3. 暴力修改:resize()
reshape 是“捏橡皮泥”(总量不变),而 resize 是“切蛋糕”或“加面粉”。它可以直接修改原数组的大小。
arr = np.array([1, 2, 3])arr.resize(5)print("变大后:", arr) # 输出: [1 2 3 0 0]arr.resize(2)print("变小后:", arr) # 输出: [1 2]
4. 增加维度:np.newaxis
有时候模型要求输入是二维的,但你手里只有一个一维数组,这时候就需要给它“加一层皮”。np.newaxis 的作用就是增加一个维度。
arr = np.array([1, 2, 3])print("原始形状:", arr.shape) # (3,)# 变成列向量col_vec = arr[:, np.newaxis]print("列向量形状:", col_vec.shape) # (3, 1)print(col_vec)# 输出:# [# [1]# [2]# [3]# ]# 变成行向量row_vec = arr[np.newaxis, :]print("行向量形状:", row_vec.shape) # (1, 3)print(row_vec)# 输出: [[1 2 3]]
总结
- 想改变形状但保留数据:用
reshape(),记得可以用 -1 偷懒。 - 想省内存且不在乎修改影响原数组:用
ravel()。
- 想改变数组大小(元素个数):用
resize()。
NumPy 数组翻转
NumPy 的数组翻转(Reversing/Flipping)可以把翻转想象成“照镜子”或者“洗牌”。
- 一维数组:就像把一列队伍倒着排,最后一个人变第一个。
在 NumPy 中,实现翻转主要有两种流派:
- “切片流派”:用
[::-1],写起来短,像黑客。 - “函数流派”:用
np.flip(),功能全,更直观。
下面整理了最实用的几种翻转姿势。
一维数组:最简单的倒序
对于一维数组,目标很简单:把 AB 变成 BA。
方法一:切片 [::-1](最 Pythonic)这是 Python 原生写法,速度极快,也是老手最爱用的。
语法解释:[开始:结束:步长]。步长为 -1 意味着“倒着走”。
import numpy as npprint('一维数组:最简单的倒序')# 1. 补全原始数组arr = np.array([1, 2, 3, 4, 5])# 2. 执行翻转reversed_arr = arr[::-1]print("原始数组:", arr)print("翻转之后:", reversed_arr)print('----------------')
方法二:np.flip()(最通用)这是 NumPy 的官方函数,语义更清晰。
arr = np.array([1, 2, 3, 4, 5])# 直接翻转reversed_arr = np.flip(arr)print("原始数组:", arr)print("翻转之后:", reversed_arr)# 输出: [5 4 3 2 1]
二维数组:上下翻 vs 左右翻
到了二维(矩阵),事情就变得有趣了。你可以选择只翻转行(上下颠倒),或者只翻转列(左右镜像),也可以全翻。
matrix = np.array([[1,2,3],[4,5,6],[7,8,9]])# --- 上下翻转(行翻转) ---# 场景:把第一行和最后一行对调。# 切片法:[::-1, :](行倒序,列不变)。# 函数法:np.flip(matrix, axis=0)。upside_down = matrix[::-1, :] # 或者: np.flip(matrix, axis=0)print("上下翻转:\n", upside_down)# --- 左右翻转 ---# 场景:照镜子,左边的变右边。# 切片法:[:, ::-1](行不变,列倒序)。# 函数法:np.flip(matrix, axis=1)。mirror_img = matrix[:, ::-1]# 或者: np.flip(matrix, axis=1)print("左右翻转:\n", mirror_img)# --- 旋转 180 度(全翻) ---# 场景:既上下翻,又左右翻。# 切片法:[::-1, ::-1]。# 函数法:np.flip(matrix)(不指定轴,默认全翻)。rotated = matrix[::-1, ::-1]print("旋转 180 度:\n", rotated)
关于 flipud 和 fliplrNumPy 早期版本经常使用以下方法:
np.flipud(arr):Up Down(上下翻,等于 axis=0)。np.fliplr(arr):Left Right(左右翻,等于 axis=1)。
建议:虽然这两个函数很方便,但更推荐你使用 np.flip(arr, axis=...),因为它的逻辑更统一,以后处理三维数组时不容易晕。这里提这两个函数主要是为了避免接手旧项目时看不懂。
重点:翻转操作通常返回的是“视图”
翻转操作通常返回的是视图,而不是副本。 这意味着,如果修改了翻转后的数组,原数组也会跟着变!(就像照镜子,你脸上画个花,镜子里的你也会变)。
print('修改视图会影响原数据')arr = np.array([1,2,3])reversed_view = arr[::-1] # 这是一个视图reversed_view[0] = 999# 修改翻转后的第一个元素(其实是原数组的最后一个)print("原数组:", arr)# 输出: [1 2 999] <-- 原数组被修改了!
修改数组维度
可以把数组想象成橡皮泥:
- 重塑:橡皮泥的总量(元素个数)不变,但你把它捏成球(1D)、捏成饼(2D)或者搓成条(3D)。
- 升维/降维:给橡皮泥加一个“厚度”,或者把它压扁。
这是数据预处理(比如把图片数据喂给神经网络)时最常用的操作。下面整理了最实用的几个案例。
重塑形状:reshape()
这是最常用的功能。核心原则只有一条:变形前后,元素的总个数必须一致。
基础用法比如有一组 1 到 12 的数据,想把它变成 3 行 4 列的表格。
import numpy as np# 原始数据:12个元素arr = np.arange(1, 13) print("原始形状:", arr.shape) # (12,)# 变成 3行4列new_arr = arr.reshape(3, 4)print("新形状:", new_arr.shape) # (3, 4)print(new_arr)
懒人神器:-1 自动推导不想算 12 / 3 = 4 怎么办?告诉 NumPy 一个维度,另一个写 -1,它会自动帮你算出来。
# 变成 2 行,列数看着办auto_arr = arr.reshape(2, -1) print("自动推导形状:", auto_arr.shape) # (2, 6)print('-------------------')
暴力修改:resize()
和 reshape 不同,resize 是个“狠人”。
- 如果新形状太大:它会重复填充原数据(或者补0,视具体参数而定)。
注意:resize 通常会直接修改原数组(原地操作),或者返回新数组但改变数据量。
arr = np.array([1,2,3])# 变大:不够就重复填arr.resize(5) print("变大后:", arr) # 输出: [1 2 3 1 2] <-- 数据被重复填充了# 变小:多了就切掉arr.resize(2)print("变小后:", arr) # 输出: [1 2]print('-------------------')
升维操作:np.newaxis
这是机器学习中最常见的操作。比如有一张照片的数据是 (高度, 宽度),但模型要求输入是 (数量, 高度, 宽度),这时就需要“升维”。 使用 np.newaxis(或者它的别名 None)来增加一个长度为 1 的维度。
arr = np.array([1,2,3]) # 形状 (3,)# 1. 变成行向量 (1行3列) -> 在第0维加一个轴row_vec = arr[np.newaxis, :] print("行向量形状:", row_vec.shape) # (1, 3)print(row_vec)# 输出: [[1 2 3]]# 2. 变成列向量 (3行1列) -> 在第1维加一个轴col_vec = arr[:, np.newaxis]print("列向量形状:", col_vec.shape) # (3, 1)print(col_vec)print('-------------------')
降维操作:squeeze()
如果有一个数组形状是 (1, 3, 1),里面有很多没用的“1”维度,你想把它压扁成 (3,),就用 squeeze()。
口诀:只挤压那些长度为 1 的维度。
arr = np.array([[[1,2,3]]]) print("原始形状:", arr.shape)# 挤压掉所有为 1 的维度clean_arr = np.squeeze(arr)print("挤压后形状:", clean_arr.shape) # (3,)print(clean_arr)# 输出: [1 2 3]print('-------------------')
展平数组:ravel() vs flatten()
把多维数组变成一维数组,这两个函数很像,但有本质区别:
代码演示:
arr = np.array([[1,2],[3,4]])# 使用 ravelflat_r = arr.ravel()flat_r[0] = 999print("原数组:", arr) # 输出: [[999 2] [ 3 4]] <-- 原数组被修改了!print('-------------------')
核心概念:视图
再次强调,reshape 和 ravel 通常返回的是视图。 这意味着它们只是给数据换了一副“眼镜”看世界,底层的内存数据没变。如果你修改了变形后的数组,原数组也会跟着变。
如果你想要一个完全独立的、不相关的数组,记得在变形后加一个 .copy(),例如:arr.reshape(3, 4).copy()。
连接数组
可以把连接想象成“拼接积木”或者“拼贴照片”。
- 二维数组:把两张照片左右拼成全景图,或者上下拼成长图。
在 NumPy 中,主要使用 np.concatenate 这个“万能胶水”,以及一些更便捷的快捷指令(如 vstack, hstack)。
基础连接:np.concatenate()
这是最通用的函数,适用于所有维度。
一维数组:首尾相连
import numpy as npprint('一维数组:首尾相连')arr1 = np.array([1,2,3])arr2 = np.array([4,5,6])# 默认连接(相当于 axis=0)result = np.concatenate((arr1, arr2))print("连接结果:", result)# 输出: [1 2 3 4 5 6]print('-------------------')
二维数组:上下拼 vs 左右拼到了二维,你必须指定方向(axis)。
axis=0:顺着行方向拼(也就是上下叠罗汉,行数增加)。axis=1:顺着列方向拼(也就是左右排排坐,列数增加)。
m1 = np.array([[1,2], [3,4]])m2 = np.array([[5,6], [7,8]])# 上下连接 (axis=0)# 默认就是 axis=0,行数变多vertical = np.concatenate((m1, m2), axis=0)print("上下连接 (axis=0):\n", vertical)# 左右连接 (axis=1)# 列数变多horizontal = np.concatenate((m1, m2), axis=1)print("左右连接 (axis=1):\n", horizontal)print('-------------------')
快捷指令:vstack 和 hstack
如果觉得记 axis=0 还是 axis=1 很麻烦,NumPy 提供了两个更符合直觉的函数:
np.vstack:Vertical(垂直/上下)堆叠。np.hstack:Horizontal(水平/左右)堆叠。
# vstack (上下叠)# 效果等同于 np.concatenate(..., axis=0)result_v = np.vstack((m1, m2))print("vstack 结果:\n", result_v)# hstack (左右拼)# 效果等同于 np.concatenate(..., axis=1)result_h = np.hstack((m1, m2))print("hstack 结果:\n", result_h)print('-------------------')
升维连接:np.stack()
这个函数和 concatenate 有一个关键区别:
concatenate 是沿现有轴连接(不增加维度,只是变长)。stack 是沿新轴连接(会增加一个维度,像叠盘子一样)。
示例:把两个一维数组变成二维矩阵
# 假设有两个一维数组,想把它变成一个二维矩阵(每一行是一个数组):arr1 = np.array([1,2,3])arr2 = np.array([4,5,6])# stack 会创建一个新的轴stacked = np.stack((arr1, arr2), axis=0)print("原始形状:", arr1.shape) # (3,)print("堆叠形状:", stacked.shape) # (2, 3) -> 变成了二维!print(stacked)print('-------------------')
常见应用场景
场景一:合并数据集(机器学习)假设有两组特征数据,每组有 10 个样本,每个样本 5 个特征。想把它们合并成一个大训练集。
# 模拟数据:10行5列data_A = np.random.rand(10, 5)data_B = np.random.rand(10, 5)# 合并样本(上下拼接,变成 20行5列)full_dataset = np.concatenate((data_A, data_B), axis=0)print("合并后形状:", full_dataset.shape) # (20, 5)
场景二:添加新特征假设已经有 10 个样本的数据,现在算出了一个新的特征列,想加进去。
# 原有数据:10行5列data = np.random.rand(10, 5)# 新特征:10行1列new_feature = np.random.rand(10, 1)# 合并特征(左右拼接,变成 10行6列)data_with_new_feature = np.hstack((data, new_feature))print("加特征后形状:", data_with_new_feature.shape) # (10, 6)print('-------------------')
避坑指南:形状必须匹配!
这是新手最容易报错的地方:除了连接的那个轴,其他轴的大小必须完全一样!
错误示范:
print('错误示范:')m1 = np.array([[1,2],[3,4]]) # 2行2列m2 = np.array([5,6]) # 1行2列# 试图左右拼接 (axis=1)# 报错!因为 m1 有2行,m2 只有1行,行数对不上,没法拼!np.concatenate((m1, m2), axis=1)
总结
- 上下拼(加行):用
axis=0 或 vstack。 - 左右拼(加列):用
axis=1 或 hstack。
分割数组
就像是切蛋糕或者切西瓜。
- 二维数组:可以横着切(分行),也可以竖着切(分列)。
在 NumPy 中,分割通常是连接的逆运算。下面整理了最实用的几种切法。
基础分割:np.split()
这是最通用的函数,适用于所有维度。
一维数组:均匀切分假设有一根长为 9 的“香肠”,把它平均切成 3 段。
import numpy as nparr = np.arange(9) # [0 1 2 3 4 5 6 7 8]# 切成 3 等份sub_arrays = np.split(arr, 3)print("分割结果:", sub_arrays)# 输出: [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]
指定位置切分如果你不想平均切,想在特定位置下刀(比如在索引 3 和 5 的位置)。
# 指定位置切分sub_arrays = np.split(arr, [4,6])print("指定位置分割:", sub_arrays)print('-------------------')
二维数组:横切 vs 竖切
到了二维,方向就很重要了。NumPy 提供了两个非常直观的专用函数:vsplit 和 hsplit。
# 假设我们有一个 4x4 的矩阵matrix = np.arange(16).reshape(4, 4)print("原始矩阵:\n", matrix)
垂直分割:np.vsplit()
V 代表 Vertical(垂直)。也就是按行切,把矩阵切成上下几块。 想象一把刀,水平挥动,把行分开。
# 切成上下 2 块(每块 2 行)up, down = np.vsplit(matrix, 2)print("上半部分:\n", up)print("下半部分:\n", down)print('-------------------')
水平分割:np.hsplit()
H 代表 Horizontal(水平)。也就是按列切,把矩阵切成左右几块。 想象一把刀,垂直挥动,把列分开。
# 切成左右 2 块(每块 2 列)left, right = np.hsplit(matrix, 2)print("左半部分:\n", left)print("右半部分:\n", right)print('-------------------')
进阶技巧:不均匀分割 np.array_split()
有时候数据不能被整除怎么办?比如你有 10 个数据,想分成 3 份,np.split 会报错,但 np.array_split 可以容忍。它会尽量平均,多出来的数据会分给前面的部分。
arr = np.arange(10) # 0 到 9# 试图分成 3 份(10 不能被 3 整除)# np.split(arr, 3) <-- 这会报错!result = np.array_split(arr, 3)print("不均匀分割:", result)print('-------------------')
常见应用场景
场景一:划分训练集和测试集这是机器学习中最常见的用法。假设你有 1000 行数据,想把前 800 行做训练,后 200 行做测试。
data = np.arange(1000)# 在索引 800 处切一刀train_data, test_data = np.split(data, [800])print("训练集大小:", train_data.shape) # (800,)print("测试集大小:", test_data.shape) # (200,)
场景二:分离特征和标签假设数据最后一列是标签(Label),前面是特征。要把它们分开。
# 模拟数据:5行3列(最后1列是标签)data = np.array([[1,2,'a'], [4,5,'b'], [7,8,'c'], [10,11,'d'], [13,14,'e']])# 左右切分:前2列是特征,最后1列是标签features, labels = np.hsplit(data, [2])print("特征:\n", features)print("标签:\n", labels)# 去掉标签多余维度y = labels[:, 0] print("压扁后的标签:", y)
数组元素的添加与删除
核心概念:NumPy 数组的大小通常是固定的。 当进行“添加”或“删除”操作时,NumPy 通常不会直接修改原数组,而是创建一个新的数组并返回。原数组保持不变。
添加元素
NumPy 提供了两个主要函数来添加元素:np.append() 和 np.insert()。
np.append():在末尾追加
- 二维数组:需要指定
axis(轴),否则数组会被压扁成一维。
import numpy as np# --- 一维数组 ---arr1 = np.array([1,2,3])new_arr1 = np.append(arr1, [4,5])print("原数组:", arr1) # [1 2 3] (原数组没变)print("追加后:", new_arr1) # [1 2 3 4 5]print('-------------------')# --- 二维数组 ---arr2 = np.array([[1,2],[3,4]])# 注意:追加的值形状必须匹配!这里我们要加一行,所以是 [5,6]new_arr2 = np.append(arr2, [[5,6]], axis=0)print("原二维数组:\n", arr2)print("追加一行后:\n", new_arr2)
注意:如果你不加 axis=0,二维数组会被强制压扁成一维:np.append(arr2, [[5,6]]) -> 结果是 [1 2 3 4 5 6]。
np.insert():在指定位置插入如果想把元素插在数组的中间,就要用 insert。
arr = np.array([1,2,3,4])# 在索引 2 的位置(即第3个位置),插入数值 99new_arr = np.insert(arr, 2, 99)print("原数组:", arr)print("插入后:", new_arr)print('-------------------')
二维数组的插入(广播机制)在二维数组中插入时,NumPy 很智能。如果你插入一个标量(比如 0),它会自动把这个标量“广播”成一行或一列。
matrix = np.array([[1,2,3],[4,5,6]])# 在索引 1 的行位置,插入全 0 行(axis=0 表示行)# 虽然只写了 0,但 NumPy 知道要填满一行new_matrix = np.insert(matrix, 1, 0, axis=0)print("插入一行 0 后:\n", new_matrix)print('-------------------')
删除元素
删除操作主要使用 np.delete()。
np.delete():删除指定索引的元素
axis:指定轴(0 是行,1 是列)。如果不指定,数组会被压扁。
arr = np.array([10,20,30,40,50])# 删除索引为 2 的元素(即 30)new_arr = np.delete(arr, 2)print("删除后:", new_arr)# 输出: [10 20 40 50]print('-------------------')# 二维数组的删除matrix = np.array([[1,2,3], [4,5,6], [7,8,9]])# 删除索引为 1 的行(即中间那行 )new_matrix = np.delete(matrix, 1, axis=0)print("删除一行后:\n", new_matrix)print('-------------------')
进阶:按值删除(布尔索引)很多初学者会问:“我想删除数组中所有的 5,怎么办?”np.delete 只能按索引删除。要按值删除,我们需要结合布尔索引。
场景:删除数组中所有的 5。
arr = np.array([1,2,3,4,5,6,5,4,3,2,1])# 逻辑:保留所有 "不等于 5" 的元素new_arr = arr[arr != 5]print("原数组:", arr)print("删除所有 5 后:", new_arr)# 输出: [1 2 3 4 6 4 3 2 1]print('-------------------')
总结
| | |
|---|
| 追加 | np.append(arr, val, axis) | |
| 插入 | np.insert(arr, index, val, axis) | |
| 删除 | np.delete(arr, index, axis) | |
| 按值删 | arr[arr != 值] | |
字符串函数
在处理数据时,我们不仅和数字打交道,经常还要处理文本(比如 CSV 文件里的名字、地址、标签等)。Python 原生的字符串处理虽然强大,但如果是处理成千上万条数据,写 for 循环会非常慢。
这时候,NumPy 的字符串函数就派上用场了。它们主要集中在 numpy.char 模块中,最大的特点是向量化——也就是说,你可以一次性对整个数组的所有字符串进行操作,速度飞快,代码也简洁。
核心模块:numpy.char
import numpy as np
字符串的连接与重复
np.char.add(arr1, arr2):连接字符串
arr1 = np.array(['Hello', 'Hi'])arr2 = np.array([' World', ' There'])# 对应位置拼接result = np.char.add(arr1, arr2)print("拼接结果:", result)# 输出: ['Hello World' 'Hi There']print('-------------------')
np.char.multiply(arr, num):重复字符串
arr = np.array(['Go', 'Run'])# 每个元素重复 3 次result = np.char.multiply(arr, 3)print("重复结果:", result)# 输出: ['GoGoGo' 'RunRunRun']print('-------------------')
大小写与格式调整
这是数据清洗中最常用的功能,比如统一把用户输入的 "USA", "usa", "UsA" 都变成 "usa"。
np.char.lower() 和 np.char.upper()全部转小写或全部转大写。
arr = np.array(['Hello', 'WORLD', 'NumPy'])print("转小写:", np.char.lower(arr))# 输出: ['hello' 'world' 'numpy']print("转大写:", np.char.upper(arr))# 输出: ['HELLO' 'WORLD' 'NUMPY']print('-------------------')
np.char.capitalize() 和 np.char.title()这两个很容易混淆,区别在于:
- capitalize:只把整个字符串的第一个字母大写,其余变小写。
- title:把每个单词的第一个字母大写(标题格式)。
arr = np.array(['hello world', 'i love numpy'])print("首字母大写 (capitalize):", np.char.capitalize(arr))# 输出: ['Hello world' 'I love numpy']print("标题格式 (title):", np.char.title(arr))# 输出: ['Hello World' 'I Love Numpy']print('-------------------')
拆分与清洗
处理脏数据时,经常需要去掉空格或拆分句子。
np.char.strip(arr):去除首尾字符默认去除空格,也可以指定去除的字符(比如去除多余的引号或星号)。
arr = np.array([' hello ', '**world**', ' numpy '])print('原数组:', arr)# 去除空格print("去空格:", np.char.strip(arr))# 输出: ['hello' '**world**' 'numpy']# 去除星号print("去星号:", np.char.strip(arr, '*'))# 输出: [' hello ' 'world' ' numpy ']print('-------------------')
np.char.split(arr):拆分字符串把字符串按分隔符切分成列表。
arr = np.array(['apple,banana,orange', 'cat,dog'])# 按逗号拆分result = np.char.split(arr, sep=',')print("拆分结果:", result)# 输出: [list(['apple', 'banana', 'orange']) list(['cat', 'dog'])]# 注意:返回的结果是一个包含列表的数组。print('-------------------')
替换与查找
np.char.replace(arr, old, new):替换内容就像 Word 里的“查找替换”功能。
arr = np.array(['I like cats', 'Cats are cute'])# 把 'cats' 替换成 'dogs'result = np.char.replace(arr, 'cats', 'dogs')print("替换结果:", result)# 输出: ['I like dogs' 'Cats are cute'] # 注意:默认区分大小写,'Cats' 没被替换print('-------------------')
np.char.center(arr, width, fillchar):居中排版常用于打印漂亮的日志或表格。
arr = np.array(['data', 'info'])# 总宽度 10,不足的部分用 '*' 填充result = np.char.center(arr, 10, fillchar='*')print("居中结果:", result)# 输出: ['***data***' '***info***']
总结
| | |
|---|
| 连接 | np.char.add(a, b) | ['a'] |
| 重复 | np.char.multiply(a, 3) | ['a'] |
| 转小写 | np.char.lower(a) | ['A'] |
| 转大写 | np.char.upper(a) | ['a'] |
| 标题化 | np.char.title(a) | ['hi'] |
| 去空格 | np.char.strip(a) | [' a '] |
| 替换 | np.char.replace(a, '旧', '新') | ['旧'] |
| 拆分 | np.char.split(a, sep=',') | 'a,b' |
这些函数在处理 Pandas 数据框(DataFrame)的字符串列时也非常常用(虽然 Pandas 有自己的 .str 访问器,但底层逻辑是相似的)。
NumPy 核心领域:数学函数
NumPy 之所以快,很大程度上是因为它提供了大量的通用函数(ufuncs)。这些函数可以直接对整个数组进行运算,而不需要你写 for 循环。
可以把这些函数分为四大类:基础运算、统计运算、高级数学函数和线性代数。
基础运算:向量化加减乘除
这是 NumPy 最基础的功能。你不需要调用函数,直接使用运算符即可,NumPy 会自动对数组中的每一个元素进行操作。
import numpy as nparr = np.array([1,2,3,4])# 加法print("加 10:", arr + 10) # [11 12 13 14]# 乘法print("乘 2:", arr * 2) # [2 4 6 8]# 平方 (幂运算)print("平方:", arr ** 2) # [1 4 9 16]# 两个数组运算arr2 = np.array([2,2,2,2])print("数组相乘:", arr * arr2) # [2 4 6 8]print('-------------------')
除了运算符,NumPy 还提供了一些特定的数学函数:
| |
|---|
np.sqrt(arr) | |
np.abs(arr) | |
np.square(arr) | |
np.power(arr, n) | |
统计运算:数据分析必备
当处理数据时,经常需要计算平均值、总和等。这些函数通常支持 axis 参数,让使用者决定是“按行算”还是“按列算”。
基础统计
arr = np.array([[1,2,3], [4,5,6]])# 求和 (np.sum)print(np.sum(arr)) # 21 (所有元素求和)print(np.sum(arr, axis=0)) # [5 7 9] (按列求和,即 1+4, 2+5, 3+6)print(np.sum(arr, axis=1)) # [6 15] (按行求和,即 1+2+3, 4+5+6)# 均值 (np.mean)print(np.mean(arr)) # 3.5print(np.mean(arr, axis=0)) # [2.5 3.5 4.5] (每列的平均值)# 最大/最小值 (np.max, np.min)print(np.max(arr)) # 6print(np.min(arr, axis=1)) # [1 4] (每行的最小值)print('-------------------')
进阶统计:离散程度
arr = np.array([1,2,3,4,5])print("均值:", np.mean(arr)) # 3.0print("标准差:", np.std(arr)) # 1.414...print('-------------------')
找位置:argmax 和 argmin
这两个函数不是返回最大值本身,而是返回最大值的索引位置。
arr = np.array([1,5,2,10,6,8])print("最大值索引:", np.argmax(arr)) # 3print('-------------------')
高级数学函数:三角与指数
NumPy 内置了科学计算器的大部分功能,直接作用于数组的每个元素。
三角函数
注意:NumPy 的三角函数参数单位是弧度,不是角度。
angles = np.array([0, np.pi/2, np.pi]) # 0, 90度, 180度print("正弦 sin:", np.sin(angles)) # 输出: [0.0000000e+00 1.0000000e+00 1.2246468e-16] (近似值)print("余弦 cos:", np.cos(angles))# 输出: [ 1.000000e+00 6.123234e-17 -1.000000e+00]print('-------------------')
指数与对数在机器学习(如逻辑回归、神经网络)中非常常用。
- 对数 (
np.log):计算自然对数 (底数是 )。
arr = np.array([0,1,2])print("指数 e^x:", np.exp(arr))# 输出: [1. 2.718 7.389]arr_log = np.array([1, np.e, np.e**2])print("对数 ln(x):", np.log(arr_log))# 输出: [0. 1. 2.]print('-------------------')
线性代数:矩阵乘法
这是 NumPy 名字中 "Numerical" 的重要部分。虽然普通乘法是元素对元素,但矩阵乘法有专门的规则。
矩阵乘法 (np.dot 或 @)
A = np.array([[1,2], [3,4]])B = np.array([[5,6], [7,8]])# 方法 1: 使用 @ 符号 (推荐)C = A @ B# 方法 2: 使用 np.dotC = np.dot(A, B)print("矩阵乘积:\n", C)# 输出: [[19 22]# [43 50]]print('-------------------')
总结
| | |
|---|
| 基础 | arr + 1 | |
| 基础 | np.sqrt(arr) | |
| 统计 | np.sum(arr, axis=0) | |
| 统计 | np.mean(arr, axis=1) | |
| 统计 | np.argmax(arr) | |
| 高级 | np.sin(arr) | |
| 高级 | np.exp(arr) | |
| 线性代数 | A @ B | |