写在前面
在上一篇文章中,我们深入探讨了面向对象编程的封装与多态。现在,我们将开启一个新的重要篇章:科学计算。无论是数据分析、机器学习还是工程仿真,高效处理数值数据都是核心能力。广为流传的数据计算三件套他们是numpy\pandas\matplotlib。
NumPy(Numerical Python)库 正是Python科学计算生态的基石。它提供了强大的多维数组对象和一系列高级数学函数,是学习Pandas、SciPy、Scikit-learn等库的必经之路。
本文将从基础概念讲起,带你快速掌握NumPy的核心用法。
上期作业要求创建一个 Employee 抽象基类,以及 Developer 和 Manager 两个子类,体现封装、继承和多态。以下是简洁的代码实现。
from abc import ABC, abstractmethod
# 1. 抽象基类 Employee
classEmployee(ABC):
def__init__(self, name, base_salary):
self._name = name # 封装:使用受保护属性
self._base_salary = base_salary
@property
defname(self):
return self._name
@abstractmethod
defcalculate_salary(self): # 多态:统一接口
pass
# 2. 子类 Developer
classDeveloper(Employee):
def__init__(self, name, base_salary, bonus):
super().__init__(name, base_salary)
self._bonus = bonus # 封装
defcalculate_salary(self): # 多态:具体实现
return self._base_salary + self._bonus
# 3. 子类 Manager
classManager(Employee):
def__init__(self, name, base_salary, team_bonus):
super().__init__(name, base_salary)
self._team_bonus = team_bonus # 封装
defcalculate_salary(self): # 多态:具体实现
return self._base_salary + self._team_bonus * 1.5
# 通关测试代码
if __name__ == "__main__":
dev = Developer("张三", 10000, 2000)
mgr = Manager("李四", 15000, 3000)
employees = [dev, mgr]
for emp in employees:
print(f"{emp.name} 的薪资是:{emp.calculate_salary()}元")
输出结果:
张三 的薪资是:12000元
李四 的薪资是:19500.0元
代码解析:此实现通过抽象基类定义统一接口,子类继承并实现具体逻辑,同时属性被良好封装,完美体现了面向对象的三大特性。
NumPy的核心是 ndarray(N维数组) 对象。它与Python列表有本质区别:
import numpy as np
# 从列表创建
arr1 = np.array([1, 2, 3, 4, 5])
print(arr1) # 输出: [1 2 3 4 5]
# 创建特殊数组
zeros_arr = np.zeros((3, 4)) # 3行4列的全0数组
ones_arr = np.ones((2, 3)) # 2行3列的全1数组
range_arr = np.arange(0, 10, 2) # 类似range,生成 [0 2 4 6 8]
random_arr = np.random.rand(2, 2) # 2x2的随机数组(0~1)
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print("形状(shape):", arr2.shape) # 输出: (2, 3)
print("数据类型(dtype):", arr2.dtype) # 输出: int64 (取决于系统)
print("维度(ndim):", arr2.ndim) # 输出: 2
无需循环即可对整个数组执行运算。
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b) # 输出: [5 7 9]
print(a * 2) # 输出: [2 4 6]
允许不同形状的数组进行算术运算。
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr + 10) # 标量10被广播到整个数组
# 输出:
# [[11 12 13]
# [14 15 16]]
与列表类似,但支持多维。
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr[0, 1]) # 输出: 2 (第0行第1列)
print(arr[1:, :2]) # 输出: [[4 5] [7 8]] (第1行到最后,每行的前2列)
arr = np.arange(12)
reshaped = arr.reshape(3, 4) # 改为3行4列的二维数组
print(reshaped)
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 垂直拼接 (沿行方向 axis=0)
v_stack = np.vstack((a, b))
# 水平拼接 (沿列方向 axis=1)
h_stack = np.hstack((a, b))
arr = np.arange(10)
split_arr = np.split(arr, [3, 7]) # 在索引3和7处分割,得到3个子数组
arr = np.array([5, 2, 8, 1, 9])
print("总和:", np.sum(arr)) # 25
print("均值:", np.mean(arr)) # 5.0
print("标准差:", np.std(arr)) # 约 3.162
print("最小值:", np.min(arr)) # 1
print("最大值:", np.max(arr)) # 9
# 可指定轴,对多维数组的某维度进行计算
arr2d = np.array([[1, 2], [3, 4]])
print("每列的和:", np.sum(arr2d, axis=0)) # 输出: [4 6]
# 生成0~1之间的均匀分布随机数
rand_uniform = np.random.rand(3, 2)
# 生成标准正态分布随机数
rand_normal = np.random.randn(3, 2)
# 生成指定范围的随机整数
rand_int = np.random.randint(1, 100, size=(5,)) # 5个1到99的整数
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 矩阵点积
dot_product = np.dot(a, b)
# 或使用 @ 运算符
dot_product_alt = a @ b
print(dot_product)
# 输出:
# [[19 22]
# [43 50]]
假设我们有一组学生的成绩数据,包含一些缺失值。
import numpy as np
# 模拟数据:5个学生,3门课程成绩,NaN代表缺失
scores = np.array([
[85, 90, np.nan],
[78, np.nan, 92],
[np.nan, 88, 85],
[90, 85, 88],
[92, 91, 95]
])
print("原始数据:\n", scores)
# 1. 处理缺失值:用该列的平均值填充
col_means = np.nanmean(scores, axis=0) # 忽略NaN计算列均值
print("各列均值:", col_means)
# 找到NaN的位置,并用对应列的均值填充
scores_filled = scores.copy()
for col inrange(scores.shape[1]):
nan_indices = np.isnan(scores_filled[:, col])
scores_filled[nan_indices, col] = col_means[col]
print("填充后数据:\n", scores_filled)
# 2. 数据筛选:找出第一门课成绩大于85的学生
good_at_first = scores_filled[scores_filled[:, 0] > 85]
print("第一门课>85的学生成绩:\n", good_at_first)
# 3. 计算统计指标:每位学生的平均分
student_avg = np.mean(scores_filled, axis=1)
print("每位学生的平均分:", student_avg)
print("全班最高平均分:", np.max(student_avg))
print("全班最低平均分:", np.min(student_avg))
案例小结:这个简单的例子展示了NumPy在数据清洗、筛选和基本统计分析中的应用,这些操作是更复杂数据分析的基础。
请完成以下作业,所有任务仅使用本文介绍的知识即可完成。
(4, 5) 的二维数组,其中所有元素均为数字 7。20 到 80(包含80),步长为 5 的一维数组。shape、dtype 和 ndim 属性。(4, 5) 数组,通过形状变换,转换为一个 (10, 2) 的新数组。p = np.array([2, 4, 6]) 和 q = np.array([1, 3, 5]),不显式使用循环,计算这两个数组对应元素的乘积之和(即点积 2*1 + 4*3 + 6*5)。[50, 100) 之间,并计算其平均值和标准差。5行3列 的数组,代表5位销售员连续3个月的销售额(单位:万元)。数据自拟,但请确保包含至少一个 np.nan 代表缺失数据。np.nanmean 并指定轴。15 万元的销售员的行索引。请将你的代码和对应的输出结果一并提交。你可以将代码写在一个Python脚本文件中,并附上运行结果的截图或文本。
任务1.2 数组属性:
形状: (13,)
数据类型: int64
维度: 1
任务2.2 点积结果: 44
任务3.2 平均销售额: [18.5 nan 22.0 19.0 25.0]
任务3.3 全部月份>15的销售员索引: [2, 4]
本文系统介绍了Python科学计算的核心库——NumPy。
我们从理解其基础数据结构 ndarray 开始,认识到它在存储效率和计算速度上相对于Python原生列表的巨大优势。通过探索向量化操作和广播机制,我们掌握了NumPy进行高效数值计算的核心思想。
文章涵盖了数组的创建、索引、切片、形状变换以及拼接分割等基本操作,并列举了求和、均值、随机数生成、点积等必备函数。最后,通过一个简单的学生成绩分析示例,我们看到了NumPy在数据处理中的实际应用。
| 导入模块 | import numpy as np | |
| 数组创建 | np.array(list) | |
np.zeros(shape) | np.zeros((3,4)) | |
np.ones(shape) | ||
np.arange(start, stop, step) | ||
np.random.rand(d0, d1, ...) | ||
| 数组属性 | arr.shape | |
arr.dtype | ||
arr.ndim | ||
| 核心特性 | 向量化操作 | arr * 2 |
| 广播机制 | ||
| 常用函数 | np.sum(arr, axis) | axis=0列,axis=1行。 |
np.mean(arr, axis) | ||
np.std(arr, axis) | ||
np.min(arr)np.max(arr) | ||
np.dot(a, b)a @ b | ||
np.nanmean(arr, axis) | 忽略NaN | |
| 数组操作 | arr.reshape(new_shape) | |
arr[index]arr[row, col] | ||
np.vstack((a, b)) | ||
np.hstack((a, b)) | ||
np.split(arr, indices) | ||
| 特殊值 | np.nan |
请在微信客户端打开