数组的 reshape 与 flatten:改变数组形状

数组变形记:从魔方到煎饼,玩转 reshape 和 flatten

各位观众老爷们,晚上好!我是你们的老朋友,人称“数组变形金刚”的码农老王。今天,咱们不聊风花雪月,也不谈人生理想,就来聊聊编程世界里一个非常实用,但也容易被忽视的小技巧:数组的 reshape 和 flatten

想象一下,你手里拿着一个魔方,刚开始它是一个完美的正方体,各种颜色规规矩矩地排列着。但是,如果你想从另一个角度观察它,或者想把它变成一个长条形,甚至把它拆成无数个小方块,你该怎么办?答案就是:变形!

在编程世界里,数组就相当于这个魔方,而 reshapeflatten 就是你手中的变形工具。它们能让你轻松地改变数组的形状,让数据以你想要的方式呈现。

一、为什么要变形?(Shape Shifting:Why Bother?)

你可能会问:“老王,数组好好的,干嘛要变形?闲得没事干吗?”

Well,这个问题问得好!就像你不能总是用魔方玩俄罗斯方块一样,在实际应用中,我们需要根据不同的场景和算法,对数组的形状进行调整。

举几个栗子🌰:

  • 图像处理: 一张图片通常以二维数组的形式存储,每个元素代表一个像素的颜色值。有时候,我们需要将图片转换成一维数组,才能方便地输入到某些机器学习模型中。
  • 机器学习: 很多机器学习算法,比如神经网络,要求输入数据是特定形状的。我们需要将原始数据进行 reshape,才能满足算法的要求。
  • 数据分析: 在处理表格数据时,我们可能需要将多行数据合并成一行,或者将一列数据拆分成多列,以便进行更深入的分析。
  • 矩阵运算: 矩阵的乘法、转置等运算,对矩阵的形状有严格的要求。我们需要确保数组的形状符合运算规则,才能得到正确的结果。

总之,数组变形就像一个“变形金刚”的技能,能让你的数据在不同的场景中灵活切换,发挥更大的作用。

二、reshape:重塑你的数据(Reshape: The Data Sculptor)

reshape 的作用就像一个雕塑家,它能让你重新塑造数组的形状,改变数组的维度和大小。

语法:

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
new_arr = arr.reshape((3, 2)) # 将 2x3 的数组变成 3x2 的数组
print(new_arr)

输出:

[[1 2]
 [3 4]
 [5 6]]

重点解读:

  • reshape() 方法接受一个元组作为参数,元组中的每个元素代表新数组的每个维度的大小。
  • reshape() 方法不会改变原始数组,而是返回一个新的数组。
  • 新数组的元素个数必须与原始数组的元素个数相同,否则会报错。 就像你不能用 6 块积木搭出一个 7 块积木的模型一样。

一些小技巧:

  • -1 的妙用: 如果你想让 NumPy 自动计算某个维度的大小,可以使用 -1。 例如:

    arr = np.array([1, 2, 3, 4, 5, 6])
    new_arr = arr.reshape((2, -1)) # NumPy 会自动计算出第二个维度的大小为 3
    print(new_arr)

    这个 -1 就像一个“万能牌”,能帮你省去一些计算的麻烦。

  • 多维数组的 reshape: reshape 不仅可以改变二维数组的形状,还可以改变多维数组的形状。 例如:

    arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) # 一个 2x2x2 的数组
    new_arr = arr.reshape((2, 4)) # 变成一个 2x4 的数组
    print(new_arr)

    可以把多维数组想象成一个“俄罗斯套娃”,reshape 可以让你改变套娃的嵌套方式。

表格总结:

操作 描述 例子
reshape(shape) 将数组变成指定形状 shape 的新数组。shape 是一个元组,包含新数组的每个维度的大小。新数组的元素个数必须与原始数组的元素个数相同。 arr = np.array([1, 2, 3, 4, 5, 6]) new_arr = arr.reshape((2, 3)) # new_arr: [[1 2 3], [4 5 6]]
reshape(-1, x) 将数组变成指定列数 x 的二维数组,行数由 NumPy 自动计算。 arr = np.array([1, 2, 3, 4, 5, 6]) new_arr = arr.reshape((-1, 2)) # new_arr: [[1 2], [3 4], [5 6]]
reshape(x, -1) 将数组变成指定行数 x 的二维数组,列数由 NumPy 自动计算。 arr = np.array([1, 2, 3, 4, 5, 6]) new_arr = arr.reshape((3, -1)) # new_arr: [[1 2], [3 4], [5 6]]
reshape(a, b, c...) 将数组变成指定形状的多维数组。 各维度的大小必须符合要求,乘积必须等于原始数组的元素总数。 arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) new_arr = arr.reshape((2, 4)) # new_arr: [[1 2 3 4], [5 6 7 8]] 这样可以把一个2x2x2的数组,变成一个2×4的数组,数据总量不变。

三、flatten:摊平你的数据(Flatten: The Pancake Maker)

flatten 的作用就像一个煎饼师傅,它能将多维数组“摊平”成一个一维数组。

语法:

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
flat_arr = arr.flatten()
print(flat_arr)

输出:

[1 2 3 4 5 6]

重点解读:

  • flatten() 方法会将多维数组按照行优先的顺序(C-style)展开成一个一维数组。
  • flatten() 方法也会返回一个新的数组,不会改变原始数组。
  • flatten() 方法没有参数,使用起来非常简单。就像摊煎饼一样,一气呵成,毫不拖泥带水。

另一种方法:ravel()

除了 flatten() 方法,NumPy 还提供了 ravel() 方法,也能实现将多维数组展开成一维数组的功能。

语法:

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
raveled_arr = arr.ravel()
print(raveled_arr)

输出:

[1 2 3 4 5 6]

flatten()ravel() 的区别:

  • flatten() 方法会创建一个原始数组的拷贝,而 ravel() 方法返回的是原始数组的视图(view)。这意味着,如果修改 ravel() 返回的数组,会影响到原始数组。
  • flatten() 方法占用的内存空间比 ravel() 方法大,因为需要复制原始数组。
  • 在大多数情况下,ravel() 方法的效率比 flatten() 方法高。

可以把 flatten() 想象成“复制粘贴”,而 ravel() 想象成“快捷方式”。

表格总结:

操作 描述 例子
flatten() 将多维数组展开成一个一维数组,返回一个拷贝,修改新数组不会影响原始数组。 arr = np.array([[1, 2, 3], [4, 5, 6]]) flat_arr = arr.flatten() # flat_arr: [1 2 3 4 5 6]
ravel() 将多维数组展开成一个一维数组,返回一个视图,修改新数组会影响原始数组。 arr = np.array([[1, 2, 3], [4, 5, 6]]) raveled_arr = arr.ravel() # raveled_arr: [1 2 3 4 5 6]

四、实战演练:变形金刚的进阶之路 (Practice Makes Perfect: The Transformer’s Journey)

光说不练假把式,接下来我们通过一些实战案例,来巩固一下 reshapeflatten 的用法。

案例一:图像处理

假设我们有一张 28×28 的灰度图像,存储在一个二维数组中。现在,我们需要将这张图像转换成一个一维数组,才能输入到神经网络中。

import numpy as np
import matplotlib.pyplot as plt # 为了显示图像

# 模拟一张 28x28 的灰度图像
image = np.random.randint(0, 256, size=(28, 28))

# 显示原始图像
plt.imshow(image, cmap='gray')
plt.title("Original Image")
plt.show()

# 将图像转换成一维数组
flattened_image = image.flatten()

# 打印一维数组的形状
print("Flattened image shape:", flattened_image.shape)

# 可以用 reshape 重新变回28x28
reshaped_image = flattened_image.reshape((28,28))

# 显示reshape之后的图像
plt.imshow(reshaped_image, cmap='gray')
plt.title("Reshaped Image")
plt.show()

案例二:数据分析

假设我们有一个包含学生信息的表格,存储在一个二维数组中。表格的每一行代表一个学生,每一列代表学生的姓名、年龄和成绩。现在,我们需要将所有学生的成绩提取出来,放到一个一维数组中。

import numpy as np

# 模拟学生信息表格
student_data = np.array([
    ['Alice', 18, 90],
    ['Bob', 19, 85],
    ['Charlie', 20, 95]
])

# 提取所有学生的成绩
scores = student_data[:, 2].astype(int) # 提取第三列(成绩),并转换为整数类型

# 打印成绩数组
print("Student scores:", scores)

案例三:矩阵运算

假设我们有两个矩阵,A 和 B。我们需要计算它们的乘积。但是,在进行矩阵乘法之前,我们需要确保 A 的列数等于 B 的行数。如果形状不匹配,我们可以使用 reshape 来调整矩阵的形状。

import numpy as np

# 定义两个矩阵
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6, 7], [8, 9, 10]])

# 计算矩阵乘积
C = np.dot(A, B)

# 打印结果
print("Matrix C:n", C)

这些案例只是冰山一角,reshapeflatten 在实际应用中还有很多其他的用途。 只要你灵活运用,就能让你的数据在不同的场景中发挥更大的作用。

五、总结:数组变形,无所不能 (Conclusion: Array Transformation, Anything is Possible)

好了,各位观众老爷们,今天的“数组变形记”就到这里告一段落了。希望通过今天的讲解,大家能够掌握 reshapeflatten 的用法,成为真正的“数组变形金刚”。

记住,数组变形就像魔方一样,需要不断地练习和尝试,才能找到最佳的解决方案。 不要害怕犯错,多动手实践,你一定会发现其中的乐趣。

最后,送给大家一句至理名言:“数据在手,reshape 在心,天下任我行!” 😉

感谢大家的观看,我们下期再见! 拜拜! 👋

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注