NumPy: 拼接与分裂

拼接与分裂

1. 你将学到

❶ concatenate 沿轴拼接 ❷ vstack / hstack 快捷方式 ❸ stack 新维度拼接 ❹ split / vsplit / hsplit 分裂 ❺ repeat / tile 重复扩展


2. 一个开发者的真实故事

(1) 痛点

Alice 有 3 个月的销售数据,每个月是一个 4×3 数组(4 个产品 × 3 个地区)。她想合并成一张大表,却不知道该用 concatenate 还是 vstack,总是搞混轴的方向。

(2) 解法

Bob 画了张示意图:"沿第 0 轴拼接行变多,沿第 1 轴拼接列变多。" concatenate(axis=0) 就是上下叠,concatenate(axis=1) 就是左右拼。

(3) 收益

掌握拼接与分裂后,Alice 能一键合并月度数据、按季度拆分、用 tile 扩展预测模板——数据组装与拆解效率提升 10 倍。


3. 知识点

(1) np.concatenate 沿轴拼接

np.concatenate 是最通用的拼接函数,通过 axis 参数指定拼接方向。

PYTHON
import numpy as np

a = np.array([[1, 2, 3],
              [4, 5, 6]])

b = np.array([[7, 8, 9],
              [10, 11, 12]])

# Along axis 0: stack vertically (rows increase)
c0 = np.concatenate([a, b], axis=0)
# [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]]

# Along axis 1: stack horizontally (columns increase)
c1 = np.concatenate([a, b], axis=1)
# [[ 1  2  3  7  8  9]
#  [ 4  5  6 10 11 12]]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。

核心规则:沿 axis=0 行变多,沿 axis=1 列变多。 拼接方向以外的维度必须一致。


(2) vstack / hstack 快捷方式

vstackhstackconcatenate 的语法糖:

快捷方式 等价于 效果
vstack([a, b]) concatenate([a, b], axis=0) 垂直拼接(行变多)
hstack([a, b]) concatenate([a, b], axis=1) 水平拼接(列变多)
PYTHON
a = np.array([[1, 2],
              [3, 4]])

b = np.array([[5, 6],
              [7, 8]])

print(np.vstack([a, b]))
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]

print(np.hstack([a, b]))
# [[1 2 5 6]
#  [3 4 7 8]]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。

对于 1D 数组,vstack 会先升维再拼接,hstack 直接首尾相连:

PYTHON
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])

print(np.vstack([x, y]))   # shape (2, 3)
# [[1 2 3]
#  [4 5 6]]

print(np.hstack([x, y]))   # shape (6,)
# [1 2 3 4 5 6]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

(3) stack 新维度拼接

stackconcatenate 的区别:stack 会创建一个新维度

PYTHON
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# stack creates a new axis
s0 = np.stack([a, b], axis=0)   # shape (2, 3)
# [[1 2 3]
#  [4 5 6]]

s1 = np.stack([a, b], axis=1)   # shape (3, 2)
# [[1 4]
#  [2 5]
#  [3 6]]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
函数 新增维度 用法
concatenate np.concatenate([a, b], axis=0)
stack np.stack([a, b], axis=0)
vstack np.vstack([a, b])
hstack np.hstack([a, b])
dstack ✅ (depth) np.dstack([a, b])

dstack 沿深度方向(第 3 轴)拼接,常用于 RGB 图像通道合并:

PYTHON
r = np.ones((2, 3))
g = np.ones((2, 3)) * 2
b_ch = np.ones((2, 3)) * 3

rgb = np.dstack([r, g, b_ch])
print(rgb.shape)  # (2, 3, 3)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

(4) split / vsplit / hsplit 分裂

splitconcatenate 的逆操作,沿指定轴将数组拆分为多个子数组。

PYTHON
a = np.arange(12)
# [0 1 2 3 4 5 6 7 8 9 10 11]

# Split into 3 equal parts
parts = np.split(a, 3)
# [array([0,1,2,3]), array([4,5,6,7]), array([8,9,10,11])]

# Split at specific positions
parts2 = np.split(a, [3, 7])
# [array([0,1,2]), array([3,4,5,6]), array([7,8,9,10,11])]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

对于 2D 数组的快捷分裂:

快捷方式 等价于 效果
vsplit(a, 2) split(a, 2, axis=0) 按行分裂
hsplit(a, 3) split(a, 3, axis=1) 按列分裂
PYTHON
a = np.arange(24).reshape(6, 4)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [12 13 14 15]
#  [16 17 18 19]
#  [20 21 22 23]]

top, bottom = np.vsplit(a, 2)
print("top:", top.shape, "bottom:", bottom.shape)
# top: (3, 4) bottom: (3, 4)

left, right = np.hsplit(a, 2)
print("left:", left.shape, "right:", right.shape)
# left: (6, 2) right: (6, 2)
# right: [[2 3], [6 7], [10 11]]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

(5) repeat vs tile

repeat 逐元素重复,tile 整体复制。

PYTHON
a = np.array([1, 2, 3])

# repeat: each element repeated N times
print(np.repeat(a, 3))
# [1 1 1 2 2 2 3 3 3]

# tile: the whole array replicated N times
print(np.tile(a, 3))
# [1 2 3 1 2 3 1 2 3]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
特性 repeat tile
重复单位 单个元素 整个数组
结果模式 aaa bbb ccc abc abc abc
多维支持 axis 参数 reps 元组
典型场景 扩展标签 生成棋盘格

2D 下的差异:

PYTHON
a = np.array([[1, 2],
              [3, 4]])

# repeat each element 2 times (flattened by default)
print(np.repeat(a, 2))
# [1 1 2 2 3 3 4 4]

# repeat along axis=0 (each row repeated)
print(np.repeat(a, 2, axis=0))
# [[1 2]
#  [1 2]
#  [3 4]
#  [3 4]]

# tile: replicate the whole array
print(np.tile(a, (2, 3)))
# [[1 2 1 2 1 2]
#  [3 4 3 4 3 4]
#  [1 2 1 2 1 2]
#  [3 4 3 4 3 4]]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

(6) append / insert / delete

这些函数也可用于拼接与删除,但总是返回副本,效率较低。

PYTHON
a = np.array([1, 2, 3])

# append (returns copy)
b = np.append(a, [4, 5])
# [1 2 3 4 5]

# insert at position
c = np.insert(a, 1, 99)
# [1 99 2 3]

# delete at position
d = np.delete(a, 1)
# [1 3]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
函数 返回值 性能 建议
np.append 副本 优先用 concatenate
np.insert 副本 少用,循环中尤其避免
np.delete 副本 用布尔索引替代
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


(7) 拼接的内存开销

所有拼接操作都会复制数据——与 reshape/transpose 等视图操作不同。

PYTHON
a = np.arange(10000).reshape(100, 100)
b = np.arange(10000, 20000).reshape(100, 100)

c = np.concatenate([a, b], axis=0)
print(np.shares_memory(a, c))  # False — data is copied!

# Memory usage: a(80KB) + b(80KB) + c(160KB) = 320KB total
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

拼接方式速查:

拼接方式 是否复制 适用场景
concatenate ✅ 复制 通用拼接
vstack ✅ 复制 垂直快捷
hstack ✅ 复制 水平快捷
stack ✅ 复制 需要新维度
append ✅ 复制 简单追加(低效)
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


(8) 拼接类型速查图

100%
graph LR
    A["拼接方式"] --> B["concatenate<br/>通用拼接"]
    A --> C["stack<br/>新增维度"]
    A --> D["repeat / tile<br/>重复扩展"]

    B --> B1["vstack<br/>axis=0"]
    B --> B2["hstack<br/>axis=1"]
    B --> B3["dstack<br/>axis=2"]

    C --> C1["stack axis=0<br/>最前新维度"]
    C --> C2["stack axis=1<br/>中间新维度"]

    D --> D1["repeat<br/>逐元素重复"]
    D --> D2["tile<br/>整体复制"]

    style A fill:#4CAF50,color:#fff
    style B fill:#2196F3,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#9C27B0,color:#fff
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

:concatenate 不同轴(难度⭐)

PYTHON
import numpy as np

a = np.array([[1, 2, 3],
              [4, 5, 6]])

b = np.array([[7, 8, 9],
              [10, 11, 12]])

# axis=0: vertical (rows grow)
v = np.concatenate([a, b], axis=0)
print(f"axis=0 shape: {v.shape}")  # (4, 3)
print(v)

# axis=1: horizontal (columns grow)
h = np.concatenate([a, b], axis=1)
print(f"axis=1 shape: {h.shape}")  # (2, 6)
print(h)

# Mismatched non-concat dimensions cause error
c = np.array([[1, 2]])  # shape (1, 2)
try:
    np.concatenate([a, c], axis=0)  # ERROR: 3 cols vs 2 cols
except ValueError as e:
    print(f"Error: {e}")
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

:vstack / hstack(难度⭐)

PYTHON
import numpy as np

a = np.array([[1, 2],
              [3, 4]])

b = np.array([[5, 6],
              [7, 8]])

# vstack = concatenate axis=0
print("vstack:")
print(np.vstack([a, b]))
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]

# hstack = concatenate axis=1
print("hstack:")
print(np.hstack([a, b]))
# [[1 2 5 6]
#  [3 4 7 8]]

# 1D arrays: vstack adds a dimension
x = np.array([10, 20])
y = np.array([30, 40])
print(f"vstack 1D: {np.vstack([x, y])}")   # shape (2, 2)
print(f"hstack 1D: {np.hstack([x, y])}")   # shape (4,)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

:stack 新维度(难度⭐⭐)

PYTHON
import numpy as np

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.array([7, 8, 9])

# stack along axis=0: new first dimension
s0 = np.stack([a, b, c], axis=0)
print(f"stack axis=0 shape: {s0.shape}")  # (3, 3)
print(s0)
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]

# stack along axis=1: new second dimension
s1 = np.stack([a, b, c], axis=1)
print(f"stack axis=1 shape: {s1.shape}")  # (3, 3)
print(s1)
# [[1 4 7]
#  [2 5 8]
#  [3 6 9]]

# stack vs concatenate
cat = np.concatenate([a.reshape(1, 3),
                       b.reshape(1, 3),
                       c.reshape(1, 3)], axis=0)
print(f"concatenate result equals stack axis=0? {np.array_equal(cat, s0)}")
# True — stack is equivalent to reshape + concatenate
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

:split 分裂(难度⭐⭐)

PYTHON
import numpy as np

# 1D split: equal parts
a = np.arange(12)
parts = np.split(a, 3)
for i, p in enumerate(parts):
    print(f"Part {i}: {p}")

# 1D split: at custom positions
parts2 = np.split(a, [4, 8])
for i, p in enumerate(parts2):
    print(f"Section {i}: {p}")

# 2D vsplit / hsplit
b = np.arange(24).reshape(4, 6)
print(f"\nOriginal: {b.shape}")

top, bottom = np.vsplit(b, 2)
print(f"vsplit -> top: {top.shape}, bottom: {bottom.shape}")

left, mid, right = np.hsplit(b, 3)
print(f"hsplit -> left: {left.shape}, mid: {mid.shape}, right: {right.shape}")

# Unequal split with indices
left2, right2 = np.hsplit(b, [2])
print(f"hsplit [2] -> left: {left2.shape}, right: {right2.shape}")
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

:repeat vs tile(难度⭐⭐)

PYTHON
import numpy as np

a = np.array([10, 20, 30])

# repeat: element-wise
print("repeat 2:", np.repeat(a, 2))
# [10 10 20 20 30 30]

# tile: whole-array replication
print("tile 2:", np.tile(a, 2))
# [10 20 30 10 20 30]

# 2D example
m = np.array([[1, 2],
              [3, 4]])

# repeat along axis
print("\nrepeat axis=0:")
print(np.repeat(m, 2, axis=0))
# [[1 2]
#  [1 2]
#  [3 4]
#  [3 4]]

# tile with (row_rep, col_rep)
print("\ntile (2,3):")
print(np.tile(m, (2, 3)))
# [[1 2 1 2 1 2]
#  [3 4 3 4 3 4]
#  [1 2 1 2 1 2]
#  [3 4 3 4 3 4]]

# Chessboard pattern with tile
white = np.array([[1, 0],
                  [0, 1]])
board = np.tile(white, (4, 4))
print(f"\nChessboard shape: {board.shape}")
print(board)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

:拼接的内存验证(难度⭐⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)
b = np.arange(12, 24).reshape(3, 4)

c = np.concatenate([a, b], axis=0)
print(f"Shares memory with a? {np.shares_memory(a, c)}")  # False
print(f"Shares memory with b? {np.shares_memory(b, c)}")  # False

# Modifying original does NOT affect concatenated result
a[0, 0] = 999
print(f"c[0,0] after modifying a: {c[0, 0]}")  # 0 — unchanged

# All concat-style operations copy data
v = np.vstack([a, b])
h = np.hstack([a, b])
s = np.stack([a, b])

for name, arr in [("vstack", v), ("hstack", h), ("stack", s)]:
    print(f"{name} shares_memory with a: {np.shares_memory(a, arr)}")
# All False
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


4. 综合示例

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。

:3 月销售数据 → 合并 → 分季度 → tile 扩展预测(难度⭐⭐⭐)

场景:Alice 有 3 个月销售数据,每个是 4×3(4 产品 × 3 地区)。她要合并成年度表、按季度拆分、用 tile 扩展预测模板。

PYTHON
import numpy as np

# Alice's monthly sales data: 4 products x 3 regions
jan = np.array([[100, 200, 150],
                [110, 210, 160],
                [120, 220, 170],
                [130, 230, 180]])

feb = np.array([[105, 205, 155],
                [115, 215, 165],
                [125, 225, 175],
                [135, 235, 185]])

mar = np.array([[110, 210, 160],
                [120, 220, 170],
                [130, 230, 180],
                [140, 240, 190]])

# Step 1: Concatenate 3 months along axis=0 (rows grow)
q1 = np.concatenate([jan, feb, mar], axis=0)
print(f"Q1 combined shape: {q1.shape}")  # (12, 3)
print("Q1 combined data:")
print(q1)

# Step 2: Split into 3 months again
jan_back, feb_back, mar_back = np.vsplit(q1, 3)
print(f"\nRecover Jan shape: {jan_back.shape}")   # (4, 3)
print(f"Matches original? {np.array_equal(jan_back, jan)}")  # True

# Step 3: Stack months as a new dimension (3, 4, 3)
monthly = np.stack([jan, feb, mar], axis=0)
print(f"\nMonthly 3D shape: {monthly.shape}")  # (3, 4, 3)
print(f"Jan from 3D: {np.array_equal(monthly[0], jan)}")  # True

# Step 4: Split into quarters (simulate Q1, Q2 by splitting)
# For demo: split each month into 2 product groups
group_a, group_b = np.hsplit(jan, [2])
print(f"\nProduct group A shape: {group_a.shape}")  # (4, 2)
print(f"Product group B shape: {group_b.shape}")  # (4, 1)

# Step 5: Tile to extend forecast template
# Use Jan average as template, tile for 12-month prediction
jan_avg = jan.mean(axis=0, keepdims=True)  # shape (1, 3)
print(f"\nJan avg template: {jan_avg}")

forecast = np.tile(jan_avg, (12, 1))  # shape (12, 3)
print(f"Forecast shape: {forecast.shape}")
print(f"All rows identical? {np.all(forecast == forecast[0])}")  # True

# Step 6: Repeat each month's avg 4 times for product-level forecast
avg_per_month = monthly.mean(axis=1)  # shape (3, 3) — 3 months x 3 regions
print(f"\nMonthly avg per region: {avg_per_month}")

expanded = np.repeat(avg_per_month, 4, axis=0)  # each month repeated 4x
print(f"Expanded forecast shape: {expanded.shape}")  # (12, 3)

# Summary
print("\n=== Pipeline Summary ===")
print(f"Original: 3 months x (4,3) = 3*12 = 36 data points")
print(f"Concatenated: (12,3) = 36 data points")
print(f"Stacked 3D: (3,4,3) = 36 data points")
print(f"Forecast tiled: (12,3) = 36 data points")
print(f"Expanded repeat: (12,3) = 36 data points")
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
⚠️ 注意: 以下代码需在本地 Python 环境中运行。


❓ 常见问题

Q concatenate 和 vstack 有什么区别?
A vstack([a, b]) 等价于 concatenate([a, b], axis=0)。vstack 是语法糖,对 1D 数组会自动升维后再拼接。建议 2D 及以上用 vstack/hstack 更简洁,1D 注意升维行为。
Q stack 会增加维度吗?
A 是的。stack 在指定轴位置插入一个新维度。例如两个 (3,) 数组 stack(axis=0) 得到 (2,3)stack(axis=1) 得到 (3,2)。concatenate 不增加维度,只在已有轴上延伸。
Q split 不等分怎么办?
A 用索引列表代替份数。np.split(a, [3, 7]) 在位置 3 和 7 处切割,产生 3 段。段长度可以不等。注意切分点必须是升序列表。
Q repeat 和 tile 有什么区别?
A repeat 逐元素重复,结果模式是 aaa bbb ccc;tile 整体复制数组,结果模式是 abc abc abc。记住:repeat 是"每个重复",tile 是"整块铺砖"。
Q 拼接会复制数据吗?
A 会。所有拼接操作(concatenate/vstack/hstack/stack/append)都会分配新内存并复制数据。这与 reshape/transpose 等视图操作不同。频繁拼接时建议预分配大数组或用 list 收集后一次性转换。
Q 循环中反复 append 为什么慢?
A 每次 np.append 都会创建新数组并复制全部数据,N 次循环的复杂度是 O(N²)。正确做法:用 list 收集,最后 np.array(list) 一次性转换,复杂度 O(N)。

📖 小节

核心心法:拼接 = 复制数据;分裂 = 复制数据。沿 axis=0 行变多,沿 axis=1 列变多。repeat 逐元素,tile 整块铺。


📝 作业

  1. 基础题(难度⭐):创建 3 个 2×3 数组(内容自定),用 np.concatenate 沿 axis=0 拼接成 6×3,再沿 axis=1 拼接成 2×9。打印每次结果的 shape。

  2. 基础题(难度⭐):创建 6×6 数组(np.arange(36).reshape(6,6)),用 hsplit 按列分成 3 等份,打印每份的 shape 和内容。

  3. 进阶题(难度⭐⭐):用 np.tile 生成 8×8 棋盘格数组(0 和 1 交替)。提示:先构造 2×2 基本块 [[1,0],[0,1]],再 tile 到 8×8

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏