0%

究极无敌之Numpy

前言

总结来说,Numpy 这个库提供了以下内容:
1. N维数组,一种多维度、同质、能快速、高效使用内存的阵列
2. 提供基于矩阵的数学运算
3. 提供线性代数,傅里叶变换和随机数生成
其中数组为其核心功能

第一次碰到numpy,还是在做线代课的大作业。用程序来模拟实现矩阵的运算,在网上搜索一番,最终选择了numpy和cv2库。代码如下:

import cv2 # openCV进行图像处理
import numpy as np # numpy进行数值计算

mat1 = np.array([
    [  0, 50,  100 ],
    [  100, 50,  0 ],
    [  150, 200,  255 ]], dtype = np.float32)
resized = np.kron(mat1, np.ones((100, 100)))  # 将矩阵放大100倍便于观看
resized = resized.astype(np.uint8)
# 将图像数据的像素值范围从其他类型(如浮点数)映射到在图像处理中常见的无符号8位整数范围
cv2.imshow('3x3 Matrix1', resized)
cv2.waitKey()
result = np.linalg.inv(mat1)
print(result)

函数

Matplotlib

Eg1 基本使用

import numpy as np 
from matplotlib import pyplot as plt 
 
x = np.arange(1,11) 
y =  2  * x +  5 
plt.title("Matplotlib demo") 
plt.xlabel("x axis caption") 
plt.ylabel("y axis caption") 
plt.plot(x,y) 
plt.show()

Eg2 汉化

使用了免费的思源黑体

# fname 为下载的字体库路径
zhfont1 = matplotlib.font_manager.FontProperties(fname="SourceHanSerifSC-Bold.otf") 
 
x = np.arange(1,11) 
y =  2  * x +  5 
plt.title("测试", fontproperties=zhfont1) 
 
# fontproperties 设置中文显示,fontsize 设置字体大小
plt.xlabel("x 轴", fontproperties=zhfont1)
plt.ylabel("y 轴", fontproperties=zhfont1)
plt.plot(x,y) 
plt.show()

反序

Eg1

arr = np.arange(9).reshape(3,3)

print(arr[::-1, :]) # 行逆序
print(arr[:, ::-1]) # 列逆序

:为选中行,::-1为逆序

Project

Project1 修改分数

假设你是一名大学教师,你在最近的期末考中失手出了巨难的考题,因此学生的成绩都不太理想。虽然如此,你很善良,不忍心大量学生因此挂科,所以你决定修改学科成绩曲线,让大家的分数看起来合理一些。

你初次批改的卷面分分别为:[42, 35, 64, 85, 51, 72, 59, 12] 这么一看,8 个人就有 5 个挂,着实有点狠了。

import numpy as np

CURVE_CENTER = 57.5  # python中用大写字母定义常量
grades = np.array([42, 35, 64, 85, 51, 72, 59, 12])


def curve(grades):
    average = grades.mean()  # 计算分数的平均数
    change = CURVE_CENTER - average  # 中位数 - 平均数 = 应加的分数
    new_grades = grades + change  # 新分数 = 原分数 + 应加分数

    return np.clip(new_grades, grades, 100)  # 使用 clip 函数限制分数上限


print(curve(grades).astype(int))  # 打印新的分数

如果不使用 NumPy 处理成绩曲线,我们需要重复为各个分数进行加分后,再进行合计。NumPy 把这些数据组合成数组后,便可以对这些数据进行统一处理,不仅去相对掉繁琐的 for 循环,让代码看起来更简洁明了,更减少了代码出现 bug 的概率。一般上,这个过程被称之为矢量化(vectorization)。

Project2 检索学生班级与成绩

因为批改大学的试卷太难了,你选择退而求其次,考了教师资格证成为高中体育老师。这一次,要用 NumPy 分别记录学生的姓名、班级和成绩。

在这次的场景中,将应用 NumPy 中的记录数组(又称之为结构化数组)。这类数组可以为每一列指定数据类别(例如:str 字符串、int 整数、bool 布尔运算等)和名称,让数据筛选变得更简单强大。

import numpy as np

data = np.array([
    ("丁一", 1, 87),
    ("刘二", 2, 68),
    ("张三", 3, 72),
    ("李四", 3, 55),
    ("王五", 3, 93),
    ("赵六", 2, 81),
    ("孙七", 1, 75),
    ("周八", 1, 88),
    ("吴九", 2, 64),
    ("郑十", 2, 49)
], dtype=[("姓名", str, 10), ("班级", int), ("分数", int)])

# 低于及格分数的学生姓名
fail = data[data["分数"] < 60]["姓名"]
print(fail)

# 分数最高的学生姓名、班级及分数
top = data[data["分数"] == np.max(data["分数"])]
print(top)

# 各班级的学生姓名、班级及分数,需按分数大小逆序排列
classes = [1, 2, 3]

for x in classes:
    student = np.sort(data[data["班级"] == x], order="分数")[::-1]
    print(student)

对于data["分数"] == np.max(data["分数"])这整个语句是新的布尔数组,[False, False, False, False, True, False, False, False, False, False] ,传入data内部后会自动选择符合条件的。
data[布尔数组] 使用这个布尔数组作为索引,选择满足条件(分数等于最大分数)的行。这个操作返回一个新的结构化数组,其中只包含满足条件的学生的信息。 和前面的其实是一个道理,data["分数"] < 60 生成了一个布尔数组,其中的每个元素表示对应学生的分数是否小于60。然后,data[data["分数"] < 60] 使用这个布尔数组作为索引,选择了分数小于60的学生的所有字段。最后,["姓名"] 部分选择了符合条件的学生中的姓名字段,得到了一个包含了分数小于60的学生姓名的数组。

参考文章

【Python 核心库】Numpy 教程与实战练习 Runoob

“富哥vivo50看看实力”