欢迎光临无锡市分类吧
详情描述

np.column_stack 是 NumPy 中一个非常实用的数组堆叠函数,它主要用于按列方向堆叠一维或二维数组。让我们深入理解它的实现原理和用法。

一、函数定义

def column_stack(tup):
    arrays = []
    for v in tup:
        arr = asanyarray(v)
        if arr.ndim < 2:
            arr = array(arr, copy=False, subok=True, ndmin=2).T
        arrays.append(arr)
    return _nx.concatenate(arrays, 1)

二、核心实现原理

1. 维度处理

  • 一维数组:会被转换为二维列向量(shape从 (n,) 变为 (n, 1)
  • 二维数组:保持原状直接使用

2. 实际等价操作

# 对于一维数组 a, b, c
np.column_stack([a, b, c])

# 等价于
np.hstack([a[:, np.newaxis], b[:, np.newaxis], c[:, np.newaxis]])

# 也等价于
np.concatenate([a[:, None], b[:, None], c[:, None]], axis=1)

三、详细示例分析

示例1:一维数组堆叠

import numpy as np

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

result = np.column_stack((a, b, c))
print(result)
# 输出:
# [[1 4 7]
#  [2 5 8]
#  [3 6 9]]

内部转换过程:

# a: [1, 2, 3] -> [[1], [2], [3]]  shape: (3,) -> (3, 1)
# b: [4, 5, 6] -> [[4], [5], [6]]  shape: (3,) -> (3, 1)
# c: [7, 8, 9] -> [[7], [8], [9]]  shape: (3,) -> (3, 1)

# 然后按 axis=1 连接:
# [[1 4 7]
#  [2 5 8]
#  [3 6 9]]

示例2:混合维度数组

# 一维和二维混合
x = np.array([1, 2, 3])          # shape: (3,)
y = np.array([[4, 5],           # shape: (3, 2)
              [6, 7],
              [8, 9]])

result = np.column_stack((x, y))
print(result)
# 输出:
# [[1 4 5]
#  [2 6 7]
#  [3 8 9]]

四、与相关函数的对比

1. np.column_stack vs np.vstack

a = [1, 2, 3]
b = [4, 5, 6]

print("column_stack:")
print(np.column_stack((a, b)))
# [[1 4]
#  [2 5]
#  [3 6]]

print("\nvstack:")
print(np.vstack((a, b)))
# [[1 2 3]
#  [4 5 6]]

2. np.column_stack vs np.hstack

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

print("column_stack:")
print(np.column_stack((a, b)))
# [[1 4]
#  [2 5]
#  [3 6]]

print("\nhstack (直接使用会出错):")
try:
    print(np.hstack((a, b)))  # 输出: [1 2 3 4 5 6]
except:
    print("需要先转换维度")

print("\nhstack (正确处理):")
print(np.hstack((a[:, None], b[:, None])))
# [[1 4]
#  [2 5]
#  [3 6]]

五、底层源码解析

查看 NumPy 源码中的实际实现:

# numpy/lib/shape_base.py 中的实际实现
def column_stack(tup):
    arrays = []
    for v in tup:
        arr = asanyarray(v)
        if arr.ndim == 1:
            arr = arr.reshape(-1, 1)  # 关键步骤:一维转二维列向量
        elif arr.ndim == 2:
            pass  # 保持原样
        else:
            raise ValueError('只支持1D或2D数组')
        arrays.append(arr)

    # 检查所有数组的行数是否相同
    n_rows = arrays[0].shape[0]
    for arr in arrays[1:]:
        if arr.shape[0] != n_rows:
            raise ValueError('所有数组必须有相同的行数')

    return concatenate(arrays, axis=1)

六、自定义实现

我们可以自己实现一个简化版的 column_stack

def my_column_stack(arrays):
    """
    自定义的 column_stack 实现
    """
    import numpy as np

    # 转换所有数组为 numpy 数组
    arrays = [np.asarray(arr) for arr in arrays]

    # 处理一维数组
    reshaped = []
    for arr in arrays:
        if arr.ndim == 1:
            # 一维数组转为列向量
            reshaped.append(arr.reshape(-1, 1))
        elif arr.ndim == 2:
            reshaped.append(arr)
        else:
            raise ValueError("数组维度不能超过2维")

    # 检查行数是否一致
    first_shape = reshaped[0].shape
    for arr in reshaped[1:]:
        if arr.shape[0] != first_shape[0]:
            raise ValueError("所有数组必须有相同的行数")

    # 沿着第二个轴(列方向)拼接
    return np.concatenate(reshaped, axis=1)

七、实用技巧和注意事项

1. 数据预处理常用模式

# 创建特征矩阵的常用方式
features = []
features.append(np.array([1, 2, 3, 4]))          # 特征1
features.append(np.array([5, 6, 7, 8]))          # 特征2
features.append(np.ones(4))                      # 偏置项

X = np.column_stack(features)
print(X)
# [[1. 5. 1.]
#  [2. 6. 1.]
#  [3. 7. 1.]
#  [4. 8. 1.]]

2. 错误处理

# 错误示例:行数不一致
a = np.array([1, 2, 3])
b = np.array([4, 5])  # 长度不同

try:
    result = np.column_stack((a, b))
except ValueError as e:
    print(f"错误: {e}")

3. 性能考虑

import time

# 大量数据时,pre-allocating 可能更快
n = 1000000
a = np.random.rand(n)
b = np.random.rand(n)
c = np.random.rand(n)

# 方法1: column_stack
start = time.time()
result1 = np.column_stack((a, b, c))
print(f"column_stack 时间: {time.time() - start:.4f}秒")

# 方法2: 预分配内存
start = time.time()
result2 = np.empty((n, 3))
result2[:, 0] = a
result2[:, 1] = b
result2[:, 2] = c
print(f"预分配时间: {time.time() - start:.4f}秒")

八、总结

np.column_stack 的核心价值在于:

自动维度处理:智能处理一维数组到列向量的转换 代码简洁性:避免了手动添加维度的繁琐操作 可读性:明确表达"按列堆叠"的意图 错误检查:内置维度一致性验证

理解其实现原理有助于:

  • 更有效地使用该函数
  • 在需要时实现自定义变体
  • 理解 NumPy 的数组操作哲学
  • 在性能关键场景中选择更优方案
相关帖子
无锡市公司注销服务-工商注册服务,专业团队为您服务,收费标准
无锡市公司注销服务-工商注册服务,专业团队为您服务,收费标准
无锡市一站式殡葬服务-白事丧事一条龙,租冰棺服务
无锡市一站式殡葬服务-白事丧事一条龙,租冰棺服务
关于信用逾期记录,有哪些广为流传但实际上并不准确的说法需要澄清?
关于信用逾期记录,有哪些广为流传但实际上并不准确的说法需要澄清?
无锡市长途转院救护车出租,120救护车出租收费多少钱
无锡市长途转院救护车出租,120救护车出租收费多少钱
无锡市殡葬电话-丧葬服务车租赁,殡葬策划
无锡市殡葬电话-丧葬服务车租赁,殡葬策划
人工授精技术诞生之前,人类为了研究繁殖做过哪些有趣的早期尝试?
人工授精技术诞生之前,人类为了研究繁殖做过哪些有趣的早期尝试?
申领出生证明提示
申领出生证明提示"没有未领取的"是什么原因,该怎么处理?
合同信息有误如何更正,解读修改流程、备注说明与补签规则
合同信息有误如何更正,解读修改流程、备注说明与补签规则
蚌埠市公司经营范围变更办理-工商注册,专业代办,一站式服务
蚌埠市公司经营范围变更办理-工商注册,专业代办,一站式服务
岳阳市病人转院租120救护车,重症急救车出租,按公里收费
岳阳市病人转院租120救护车,重症急救车出租,按公里收费
内江市定制化网站开发#专业网站建设设计,收费标准
内江市定制化网站开发#专业网站建设设计,收费标准
面试时面试官挑了一下眉又很快收回,是不是对你的回答有疑问?
面试时面试官挑了一下眉又很快收回,是不是对你的回答有疑问?
被公司优化离职后,第一周最该做的五件事你真的清楚吗?
被公司优化离职后,第一周最该做的五件事你真的清楚吗?
在短视频时代,传统戏曲是如何通过新媒介吸引年轻观众群体的?
在短视频时代,传统戏曲是如何通过新媒介吸引年轻观众群体的?
三亚市殡葬一条龙公司-丧葬服务办理,殡礼布置
三亚市殡葬一条龙公司-丧葬服务办理,殡礼布置
珠海市救护车接送患者转院,正规长途120救护车出租
珠海市救护车接送患者转院,正规长途120救护车出租
银川市公司注册资本变更代办服务-公司注册,专业团队为您服务,收费透明
银川市公司注册资本变更代办服务-公司注册,专业团队为您服务,收费透明
邵阳市代办食品许可证|公司注册,专业一站式服务
邵阳市代办食品许可证|公司注册,专业一站式服务
当工作年限达到不同门槛时,法定的带薪年休假天数会自动增加吗?
当工作年限达到不同门槛时,法定的带薪年休假天数会自动增加吗?
火灾发生时先找毛巾沾水还是先往外跑,十几秒的犹豫会错过什么?
火灾发生时先找毛巾沾水还是先往外跑,十几秒的犹豫会错过什么?