查看全课大纲(第 29 / 101 节)
  1. 1.数据分析基本概念
  2. 2.学习数据分析的一般路线
  3. 3.数据分析的流程
  4. 4.数据类型
  5. 5.环境部署(1)
  6. 6.环境部署(2)
  7. 7.课程介绍
  8. 8.TXT文件操作
  9. 9.JSON文件操作
  10. 10.CSV文件操作
  11. 11.Excel文件操作
  12. 12.数据库及SQL常用语法
  13. 13.数据库基本操作
  14. 14.数据库多表连接
  15. 15.实战:欧洲职业足球数据库分析
  16. 16.爬虫简介
  17. 17.URL管理模块
  18. 18.网页下载模块
  19. 19.网页解析模块(1)
  20. 20.网页解析模块(2)
  21. 21.Scrapy简介
  22. 22.Scrapy使用步骤(1)
  23. 23.Scrapy使用步骤(2)
  24. 24.Scrapy使用步骤(3)
  25. 25.Scrapy使用步骤(4)
  26. 26.实战:获取国内城市空气质量指数数据
  27. 27.NumPy和SciPy介绍
  28. 28.多维数组
  29. 29.多维数组操作
  30. 30.NumPy的常用方法
  31. 31.向量化介绍
  32. 32.向量化及通用函数
  33. 33.实战:2016美国大选分析
  34. 34.数据结构-Series
  35. 35.数据结构-DataFrame
  36. 36.数据结构-Index
  37. 37.Series的索引操作
  38. 38.DataFrame的索引操作
  39. 39.索引操作总结
  40. 40.运算与对齐
  41. 41.函数应用操作(1) -- map
  42. 42.函数应用操作 (2) -- apply applymap
  43. 43.文件读写操作
  44. 44.排序操作
  45. 45.数据清洗--处理缺失数据
  46. 46.数据清洗--处理重复数据
  47. 47.数据清洗--替换数据
  48. 48.常用统计方法(1) -- describe quantile
  49. 49.常用统计方法(2) -- sum mean median count
  50. 50.常用统计方法(3) -- max min idxmax idxmin
  51. 51.常用统计方法(4) -- mad var std cumsum
  52. 52.实战:全球食品数据分析
  53. 53.层级索引
  54. 54.分组与聚合介绍
  55. 55.分组操作(1) -- GroupBy对象及常用聚合操作
  56. 56.分组操作(2) -- 自定义分组及聚合操作
  57. 57.透视表介绍
  58. 58.透视表操作
  59. 59.数据规整(1) -- 数据合并concat
  60. 60.数据规整(2) -- 数据连接merge
  61. 61.数据重构(3) -- 数据重构stack unstack
  62. 62.实战:互联网电影资料库分析
  63. 63.探索性数据分析EDA介绍
  64. 64.EDA的目的
  65. 65.EDA常用工具
  66. 66.Matplotlib绘图基本介绍
  67. 67.Matplotlib画布
  68. 68.散点图和柱状图的绘制
  69. 69.直方图的绘制
  70. 70.矩阵绘图
  71. 71.子图的使用
  72. 72.Matplotlib颜色、标记、线型
  73. 73.Matplotlib坐标刻度、标签、图例、标题
  74. 74.Seaborn介绍
  75. 75.数据集分布可视化(1) -- 单变量分布、双变量分布
  76. 76.数据集分布可视化(2) -- 变量关系可视化
  77. 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
  78. 78.交互式数据可视化工具Bokeh介绍
  79. 79.Bokeh绘制散点图、柱状图、盒子图、弦图
  80. 80.Bokeh绘制常用图形元素
  81. 81.3D绘图 -- mplot3d
  82. 82.3D曲线可视化
  83. 83.3D散点图可视化
  84. 84.3D柱状图可视化
  85. 85.Pandas绘图
  86. 86.实战:Lending Club借贷数据探索性分析及可视化
  87. 87.机器学习介绍及应用场景
  88. 88.机器学习建模介绍 (1) -- 分类
  89. 89.机器学习建模介绍 (2) -- 回归
  90. 90.机器学习建模介绍 (3) -- 聚类
  91. 91.机器学习分类
  92. 92.机器学习工具scikit-learn
  93. 93.使用scikit-learn的流程
  94. 94.数据集准备及划分
  95. 95.模型选择
  96. 96.数据预处理及特征工程
  97. 97.过拟合与欠拟合
  98. 98.模型调参介绍
  99. 99.模型调参方法
  100. 100.模型测试及评价
  101. 101.实战:通过移动设备行为数据预测性别和年龄

多维数组操作

约 16 分钟

📺 正在播放小象学院官方高清录播(支持倍速与清晰度调节)

小象实战讲义 · Python数据分析实战

在上一节我们学习了如何创建多维数组并查看其属性。本节我们将深入多维数组的核心操作:如何从数组中获取我们想要的数据。这包括通过索引和切片来定位数据,通过条件来筛选数据,以及通过转置来改变数据的排列方式。掌握这些操作是后续进行数据计算和分析的基础。

💡 核心导读

  • 索引与切片:学习如何像操作列表一样,通过位置获取一维和多维数组中的单个元素或连续区域。
  • 条件索引:掌握使用布尔数组作为“遮罩”,根据条件(如“大于某个值”)高效过滤数据的方法。
  • 转置操作:理解并实践三种交换数组行列(轴)的方法:.T 属性、np.transpose() 函数和 np.swapaxes() 函数。

索引与切片:精准定位数据

NumPy 数组的索引和切片操作与 Python 列表非常相似,但扩展到了多个维度。我们可以通过指定每个维度上的位置或范围来获取数据。

一维数组索引

一维数组的索引与列表完全相同,使用方括号 [],索引从 0 开始。

import numpy as np

# 创建一维数组
data_1d = np.array([1, 2, 3, 4, 5, 6])
print("一维数组:", data_1d)

# 索引操作
print("data_1d[0]:", data_1d[0])   # 获取第一个元素
print("data_1d[-1]:", data_1d[-1]) # 获取最后一个元素
print("data_1d[3:]:", data_1d[3:]) # 从索引3开始切片到末尾
一维数组: [1 2 3 4 5 6]
data_1d[0]: 1
data_1d[-1]: 6
data_1d[3:]: [4 5 6]

多维数组索引

对于二维及以上的数组,索引方式变为 arr[行切片, 列切片, ...]。逗号用于分隔不同维度的索引。

import numpy as np

# 创建3行3列的二维数组
data_2d = np.arange(9).reshape(3, 3)
print("原始二维数组:\n", data_2d)
print("数组形状 (shape):", data_2d.shape)

# 1. 获取连续区域:前两行,从第1列到末尾
slice_1 = data_2d[:2, 1:]
print("\n1. data_2d[:2, 1:]:\n", slice_1)
print("   子数组形状:", slice_1.shape)

# 2. 获取单行数据(三种等价方式)
row_single = data_2d[2]
row_slice = data_2d[2, :]
row_slice_expanded = data_2d[2:, :]
print("\n2. 获取第三行数据:")
print("   data_2d[2]:", row_single, "形状:", row_single.shape)
print("   data_2d[2, :]:", row_slice, "形状:", row_slice.shape)
print("   data_2d[2:, :]:\n", row_slice_expanded, "形状:", row_slice_expanded.shape)

# 3. 获取所有行,前两列
slice_all_rows = data_2d[:, :2]
print("\n3. data_2d[:, :2]:\n", slice_all_rows)
print("   子数组形状:", slice_all_rows.shape)

# 4. 获取单个元素与子数组
elem = data_2d[1, :2]          # 获取第二行的前两个元素(一维)
sub_arr = data_2d[1:2, :2]     # 获取第二行(仅一行)的前两列(二维)
print("\n4. 对比单个元素与子数组:")
print("   data_2d[1, :2]:", elem, "形状:", elem.shape)
print("   data_2d[1:2, :2]:\n", sub_arr, "形状:", sub_arr.shape)
原始二维数组:
 [[0 1 2]
 [3 4 5]
 [6 7 8]]
数组形状 (shape): (3, 3)

1. data_2d[:2, 1:]:
 [[1 2]
 [4 5]]
   子数组形状: (2, 2)

2. 获取第三行数据:
   data_2d[2]: [6 7 8] 形状: (3,)
   data_2d[2, :]: [6 7 8] 形状: (3,)
   data_2d[2:, :]:
 [[6 7 8]] 形状: (1, 3)

3. data_2d[:, :2]:
 [[0 1]
 [3 4]
 [6 7]]
   子数组形状: (3, 2)

4. 对比单个元素与子数组:
   data_2d[1, :2]: [3 4] 形状: (2,)
   data_2d[1:2, :2]:
 [[3 4]] 形状: (1, 2)

关键理解:

  • data_2d[2] 和 data_2d[2, :] 都返回第三行的所有元素,结果是一维数组。
  • data_2d[2:, :] 虽然数据也是第三行,但因为行切片 2: 产生了一个范围,所以结果是一个形状为 (1, 3) 的二维数组。
  • 同理,data_2d[1, :2] 获取的是第二行前两个元素(一维),而 data_2d[1:2, :2] 获取的是“第二行”这个子集的前两列(二维)。

条件索引:按需过滤数据

条件索引(布尔索引)允许我们根据逻辑条件来筛选数组元素。其核心思想是:先创建一个与原始数组形状相同的布尔数组(遮罩),其中 True 表示对应位置的元素满足条件,然后使用这个布尔数组作为索引来提取数据。

import numpy as np

# 重新创建示例数组
data = np.arange(9).reshape(3, 3)
print("原始数组:\n", data)

# 单个条件:找出大于4的数据
print("\n--- 单个条件过滤 ---")
# 方法1:分步操作
mask = data > 4
print("布尔掩码 (data > 4):\n", mask)
result = data[mask]
print("过滤结果 (data[mask]):", result)

# 方法2:一步到位(常用简写)
result_short = data[data > 4]
print("简写结果 (data[data > 4]):", result_short)

# 多条件组合:找出大于4的偶数
print("\n--- 多条件组合过滤 ---")
# 注意:多个条件必须用括号括起来,并使用位运算符 & (与)、| (或)
condition = (data > 4) & (data % 2 == 0)
print("组合条件 ((data > 4) & (data % 2 == 0)):\n", condition)
result_multi = data[condition]
print("过滤结果 (大于4的偶数):", result_multi)
原始数组:
 [[0 1 2]
 [3 4 5]
 [6 7 8]]

--- 单个条件过滤 ---
布尔掩码 (data > 4):
 [[False False False]
 [False False  True]
 [ True  True  True]]
过滤结果 (data[mask]): [5 6 7 8]
简写结果 (data[data > 4]): [5 6 7 8]

--- 多条件组合过滤 ---
组合条件 ((data > 4) & (data % 2 == 0)):
 [[False False False]
 [False False False]
 [ True False  True]]
过滤结果 (大于4的偶数): [6 8]

重要提醒:

  • 组合多个条件时,必须使用位运算符 & (与)、| (或),而不是 Python 的关键字 and、or。
  • 每个条件必须用括号括起来,以确保运算优先级正确。

转置操作:交换数据视角

转置是线性代数中的常见操作,在 NumPy 中意味着交换数组的轴(axes)。对于二维数组,转置就是行变列、列变行。

NumPy 提供了三种实现转置的方法:

  1. .T 属性:最简单直接。
  2. np.transpose() 函数:功能更通用,可以指定转置后的轴顺序(对高维数组有用)。
  3. np.swapaxes() 函数:交换指定的两个轴。
import numpy as np

# 创建一个3行5列的数组
data_t = np.arange(15).reshape(3, 5)
print("原始数组 (3行 x 5列):\n", data_t)
print("原始形状:", data_t.shape)

# 方法1:使用 .T 属性
transposed_T = data_t.T
print("\n1. 使用 .T 属性转置后 (5行 x 3列):\n", transposed_T)
print("   转置后形状:", transposed_T.shape)

# 方法2:使用 np.transpose() 函数
transposed_func = np.transpose(data_t)
print("\n2. 使用 np.transpose() 转置后:\n", transposed_func)

# 方法3:使用 np.swapaxes() 交换轴
# 对于二维数组,轴0是行,轴1是列。交换它们即实现转置。
transposed_swap = np.swapaxes(data_t, 0, 1)
print("\n3. 使用 np.swapaxes(data, 0, 1) 交换轴后:\n", transposed_swap)

# 验证三种方法结果是否相同
print("\n验证: .T, transpose(), swapaxes() 结果是否完全相同?")
print("T == transpose?", np.array_equal(transposed_T, transposed_func))
print("T == swapaxes?", np.array_equal(transposed_T, transposed_swap))
原始数组 (3行 x 5列):
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
原始形状: (3, 5)

1. 使用 .T 属性转置后 (5行 x 3列):
 [[ 0  5 10]
 [ 1  6 11]
 [ 2  7 12]
 [ 3  8 13]
 [ 4  9 14]]
   转置后形状: (5, 3)

2. 使用 np.transpose() 转置后:
 [[ 0  5 10]
 [ 1  6 11]
 [ 2  7 12]
 [ 3  8 13]
 [ 4  9 14]]

3. 使用 np.swapaxes(data, 0, 1) 交换轴后:
 [[ 0  5 10]
 [ 1  6 11]
 [ 2  7 12]
 [ 3  8 13]
 [ 4  9 14]]

验证: .T, transpose(), swapaxes() 结果是否完全相同?
T == transpose? True
T == swapaxes? True

如何选择?

  • 对于简单的二维数组转置,使用 .T 属性最方便。
  • 对于三维或更高维的数组,当需要复杂的轴重排时,np.transpose() 可以指定新的轴顺序,np.swapaxes() 则专门用于交换两个指定的轴。

📝 动手练一练

  1. 概念辨析:给定一个二维数组 arr = np.arange(12).reshape(3, 4),请问 arr[1, 2]、arr[1][2] 和 arr[1:2, 2:3] 这三种索引方式获取的结果在数据结构(维度)和数值上有什么相同和不同?
👉 点击查看参考答案
import numpy as np
arr = np.arange(12).reshape(3, 4)
print("arr[1, 2] 的值:", arr[1, 2], ",类型:", type(arr[1, 2]).__name__)
print("arr[1][2] 的值:", arr[1][2], ",类型:", type(arr[1][2]).__name__)
print("arr[1:2, 2:3] 的值:\n", arr[1:2, 2:3], ",形状:", arr[1:2, 2:3].shape)
arr[1, 2] 的值: 6 ,类型: int64
arr[1][2] 的值: 6 ,类型: int64
arr[1:2, 2:3] 的值:
 [[6]] ,形状: (1, 1)
  • arr[1, 2]:获取第2行第3列(索引从0开始)的单个标量值,结果是 6,类型是 numpy.int64(与上方印刷输出显示的 int64 一致)。
  • arr[1][2]:先获取第2行(一维数组 [4 5 6 7]),再从这个一维数组中获取索引为2的元素。结果也是标量值 6。虽然结果相同,但这是两次索引操作,效率略低于 arr[1, 2]。
  • arr[1:2, 2:3]:获取第2行(仅一行)和第3列(仅一列)交叉的子数组。结果是一个形状为 (1, 1) 的二维数组 [[6]],里面包含同一个值 6,但数据结构不同。
  1. 动手实算:创建一个形状为 (4, 4) 的数组,元素为 0 到 15。请编写一行代码,使用条件索引筛选出数组中所有能被 3 整除的元素。
👉 点击查看参考答案
import numpy as np
arr = np.arange(16).reshape(4, 4)
result = arr[arr % 3 == 0]
print("原始数组:\n", arr)
print("\n能被3整除的元素:", result)
原始数组:
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

能被3整除的元素: [ 0  3  6  9 12 15]

输出结果应为:[0, 3, 6, 9, 12, 15]。关键点是使用布尔表达式 arr % 3 == 0 作为索引。

本章小结

本节我们掌握了操作 NumPy 多维数组的三大核心技能:索引切片用于定位、条件索引用于筛选、转置操作用于变换数据排列。这些操作是后续进行向量化计算和数据分析的基石。

📋 行动清单

  • 在 Python 环境中,尝试对一个 5x5 的数组进行各种切片操作,并打印其 shape,直观感受维度变化。
  • 使用条件索引,从一个模拟的成绩数组中筛选出所有大于 90 分的分数。
  • 对一个三维数组 (2, 3, 4) 使用 .T、np.transpose() 和 np.swapaxes(),观察结果并理解轴的变化。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 本节课件:多维数组操作
    PDF · 308KB
    下载
  • 全套课件打包(第1-5章)
    ZIP · 12.8MB
    下载
  • 全套课件打包(第6-8章)
    ZIP · 15MB
    下载
  • 实战数据集:AppleStore 应用商城分析
    ZIP · 329KB
    下载
  • 实战数据集:女性服装电商分析
    ZIP · 2.8MB
    下载
  • Python 数据分析环境搭建指南
    PDF · 2MB
    下载
  • Scrapy 安装教程
    PDF · 12.7MB
    下载
  • 附加实战项目:AppleStore 应用商城数据分析
    ZIP · 0.3MB · ipynb + CSV 数据
    下载
  • 附加实战项目:银行电话营销数据分析
    ZIP · 0.4MB · ipynb + CSV 数据
    下载
  • 附加实战项目:女性服装电商评论数据分析
    ZIP · 2.7MB · ipynb + CSV 数据
    下载
  • 附加实战项目:美国化学学会杂志数据分析
    ZIP · 34.2MB · ipynb + SQLite 数据库
    下载