Python与线性代数:Numpy基础知识I

Numpy是python里最为重要的库之一,它提供了许多强大的处理多维数组的函数,相较于传统的列表,ndarray同样具有可变性, 但数据类型必须是统一的,此外,ndarray具备极高的内存效率与丰富的功能拓展。其多维数组的特性使得其在线性代数计算方面有着独一无二的优势

I、创建ndarray

第一种方案:直接创建

    #最简单的一维数组
    arr1=np.array([1,2,3,4,5])
    print(arr1) #输出[1 2 3 4 5]
    #多维数组,用逗号把多个一维数组隔开,外面加一个大的方括号,相当于矩阵
    arr2=np.array([[1,2,3],[4,5,6]])
    print(arr2) #输出[[1 2 3]
                #    [4 5 6]]
    #规定数据类型的创建
    arr3=np.array([1,2,3],dtype=np.float64)
    print(arr3) #输出[1. 2. 3.]
    #规定最小维度为2的创建
    arr4=np.array([1,2,3],ndmin=2)
    print(arr4) #输出[[1 2 3]]
                

第二种方案:从已有数组创建

    #从已有列表创建
    a=[0,0,1,4]
    b=np.array(a)
    print(b) #输出[0 0 1 4]
    type(b) #输出numpy.ndarray
    #从已有元组创建
    c=(1,2,3)
    d=np.array(c)
    print(d) #输出[1 2 3]
    type(d) #输出numpy.ndarray

    #注意区别np.array和np.asarray两种函数
    #numpy.asarray 类似 numpy.array,但 numpy.asarray 参数只有三个,比 numpy.array 少两个。
    #当数据源不是 ndarray(如列表、元组等)时,np.array 和 np.asarray 的行为一致,都会生成一个新的 ndarray。
    #当数据源是 ndarray 时:
    1.np.array 复制数据,生成新的 ndarray,即数据独立
    2.np.asarray 直接返回引用,不复制数据,即数据共享

第三种方案:等差创建

    #np.arange(start,stop,step,dtype)
    #start:起始值,默认为0
    #stop:终止值(不包含)
    print(np.arange(0, 10, 2))  # 输出: array([0, 2, 4, 6, 8])

    #np.linspace(start,stop,num,endpoint,dtype)
    #start:起始值,默认为0
    #stop:终止值(包含)
    #num:生成的等间隔样例数量,默认为50
    #endpoint:序列中是否包含stop值,默认为True
    print(np.linspace(0, 1, 5))  # 输出: array([0., 0.25, 0.5, 0.75, 1.])

    #可用reshape等函数将等差创建的一维数组延展到多维

第四种方案:一个数字填满整个数组

    #numpy.zeros(shape, dtype , order )
    #shape:数组形状
    #dtype:数据类型,可选,默认浮点数
    #order:可选,有"C"和"F"两个选项,分别代表,行和列
    arr1 = np.zeros(5)  
    print(arr1)# 输出: [0. 0. 0. 0. 0.]
    arr2 = np.zeros((2, 3))  
    print(arr2)            # 输出: [[0. 0. 0.]
                           #        [0. 0. 0.]]
    #类似的还有: numpy.ones(shape, dtype , order )
    
    #numpy.full(shape, fill_value, dtype, order)
    # 创建长度为5的一维数组,填充值为7
    arr_1d = np.full(5, 7)
    print(arr_1d)  # 输出: [7 7 7 7 7]
    # 创建形状为(2, 3)的二维数组,填充值为8
    arr_2d = np.full((2, 3), 8)
    print(arr_2d)  # 输出: [[8 8 8]
                   #        [8 8 8]]

    #由于numpy里初始化空数组的函数为往数组里随机添加数字,往往实际使用时会选择用numpy.zeros之类的函数代替

II、索引与切片

    #ndarray的切片具有极强的灵活性,有些类似于列表
    arr = np.array([1,2,3,4,5,6,7,8,9])
    print(arr[5:8])   #输出:[6 7 8]
    arr[5:8]=10
    print(arr)   #输出:[ 1  2  3  4  5 10 10 10  9]

    #值得注意的是,这样快捷的切片方式是浅拷贝,这也意味着对切片部分的改动,会影响原有数组
    arr1 = np.array([1,2,3,4,5,6,7,8,9])
    arr1_slice= arr1[5:8]
    arr1_slice[:]=88
    print(arr1)   #输出:[ 1  2  3  4  5 88 88 88  9]

    #如果想要避免这种情况,可以使用copy函数深拷贝
    arr2 = np.array([1,2,3,4,5,6,7,8,9])
    arr2_slice= arr2[5:8].copy()

    #接下来讲讲多维数组的切片
    arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    # 取第一行
    print(arr2d[0])  # 输出: [1 2 3]
    # 取第一列
    print(arr2d[:, 0])  # 输出: [1 4 7]
    # 取前两行
    print(arr2d[:2])  # 输出: [[1 2 3]
                     #        [4 5 6]]
    # 取前两列
    print(arr2d[:, :2])  # 输出: [[1 2]
                         #        [4 5]
                         #        [7 8]]
    # 选取任意你想要的部分,如:
    print(arr2d[:2, 1:])  # 输出: [[2 3]
                         #        [5 6]]
    
    #总结:第一位表示axis0的取向(纵),第二位表示axis1的取向(横)                     

    

布尔索引与数据筛选

    #布尔索引(Boolean Indexing)是NumPy中一种强大且高效的数据选择方法,它允许你使用布尔值(True/False)数组来选择数组中的元素
    arr = np.array([1, 2, 3, 4, 5])
    mask = np.array([True, False, True, False, True]) #布尔掩码(副本)
    print(arr[mask])  # 输出: [1 3 5]

    # 这里示范使用布尔索引筛选出数组中的奇数元素
    arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
    mask = arr % 2 == 1
    print(mask) # 输出:[ True False  True False  True False  True False  True]
    print(arr[mask])  # 输出: [1 3 5 7 9]

    #判定条件的设置非常灵活
    arr = np.array([10, 20, 30, 40, 50])
    print(arr[arr > 30])  #输出: [40 50]
    print(arr[(arr > 20) & (arr < 50)])  #输出: [30 40]

    #多维数组也能用
    arr1 = np.array([[1, 2, 3], 
               [4, 5, 6], 
               [7, 8, 9]])
    print(arr1[arr1 > 5])  # [6 7 8 9]

    arr2 = np.array([[1, 2], [3, 4], [5, 6]])
    mask = np.array([True, False, True])
    print(arr2[mask])  # 选择第0行和第2行
                    # 输出:
                            # [[1 2]
                            #  [5 6]]
    

布尔索引与数据处理

    #批量修改元素数值
    arr = np.array([1, 2, 3, 4, 5])
    arr[arr > 3] = 99
    print(arr)  # [ 1  2  3 99 99]

    #清洗异常数值
    data = np.array([1, 2, np.nan, 4, 5, np.nan, 7])
    clean_data = data[~np.isnan(data)]
    print(clean_data)  # [1. 2. 4. 5. 7.]

布尔索引与图像处理

import numpy as np
import matplotlib.pyplot as plt

# 生成100x100的灰度图像(0-99)
image = np.zeros(shape=(100, 100), dtype=np.uint8)
for i in range(100):
    image[i, :] = i  # 每行像素值等于行号

# 布尔索引示例1:将大于50的像素设为255(白色)
thresholded = image.copy()
thresholded[thresholded > 50] = 255

# 布尔索引示例2:创建黑白相间的条纹图案
striped = image.copy()
striped[(striped % 20) < 10] = 0    # 每20像素中前10设为黑色
striped[(striped % 20) >= 10] = 255  # 后10设为白色

# 布尔索引示例3:创建中心高亮区域
center_highlight = image.copy()
y, x = np.ogrid[:100, :100]
mask = (x-50)**2 + (y-50)**2 <= 30**2  # 半径为30的圆形区域
center_highlight[mask] = 255           # 圆形区域内设为白色

# 显示所有图像
plt.figure(figsize=(15, 10))

# 原始图像
plt.subplot(2, 2, 1)
plt.imshow(image, cmap='gray')
plt.title("Original Image")
plt.axis('off')

# 阈值处理
plt.subplot(2, 2, 2)
plt.imshow(thresholded, cmap='gray')
plt.title("Threshold >50")
plt.axis('off')

# 条纹图案
plt.subplot(2, 2, 3)
plt.imshow(striped, cmap='gray')
plt.title("Striped Pattern")
plt.axis('off')

# 中心高亮
plt.subplot(2, 2, 4)
plt.imshow(center_highlight, cmap='gray')
plt.title("Center Highlight")
plt.axis('off')

plt.tight_layout()
plt.show()
example

花式索引:更加灵活的切片(副本)

arr = np.array([10, 20, 30, 40, 50, 60, 70])
print(arr[[1, 3, 5]])  # 输出: [20 40 60]
# 元素可以重复选择
print(arr[[0, 0, 2, 2, 2]])  # 输出: [10 10 30 30 30]
# 可以改变顺序
print(arr[[6, 4, 2, 0]])  # 输出: [70 50 30 10]
# 多维数组里的使用
arr_2d = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9],
                  [10, 11, 12]])

# 选择第0行和第2行
print(arr_2d[[0, 2]])# 输出: [[1 2 3]
                           #  [7 8 9]]