知远漫谈头像
关注
Python NumPy - 数组的拼接 concatenate 函数横向与纵向拼接封面图

Python NumPy - 数组的拼接 concatenate 函数横向与纵向拼接

在这里插入图片描述

👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕NumPy这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


Python NumPy 数组拼接:深入理解 concatenate 函数的横向与纵向拼接 🧠

在数据科学和机器学习的世界中,数组操作是日常工作的核心部分。NumPy 作为 Python 中最基础且强大的数值计算库,提供了丰富的数组操作功能。其中,concatenate 函数是进行数组拼接的核心工具之一。今天,我们将深入探讨这个函数的各种用法,从基础概念到高级应用,帮助你全面掌握数组拼接的艺术。🎨

什么是 NumPy concatenate 函数?🔍

numpy.concatenate 是一个用于沿指定轴连接一系列数组的函数。它允许我们将多个数组按照特定的方式组合在一起,形成一个新的、更大的数组。这个函数的基本语法如下:

numpy.concatenate((a1, a2, ...), axis=0, out=None)

其中:

  • a1, a2, ...:需要连接的数组序列
  • axis:连接的轴,默认为0
  • out:可选参数,用于指定输出数组

让我们从最简单的例子开始:

import numpy as np

# 创建两个一维数组
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])

# 横向拼接(默认axis=0)
result = np.concatenate((arr1, arr2))
print("一维数组拼接结果:", result)
# 输出: [1 2 3 4 5 6]

理解轴(Axis)的概念 🎯

在深入学习之前,我们需要先理解"轴"的概念。轴是数组维度的索引,对于二维数组来说:

  • axis=0 表示沿着行的方向(纵向)
  • axis=1 表示沿着列的方向(横向)
# 创建两个二维数组
matrix1 = np.array([[1, 2], 
                    [3, 4]])
matrix2 = np.array([[5, 6], 
                    [7, 8]])

print("矩阵1:")
print(matrix1)
print("\n矩阵2:")
print(matrix2)

# axis=0 纵向拼接
vertical_concat = np.concatenate((matrix1, matrix2), axis=0)
print("\n纵向拼接 (axis=0):")
print(vertical_concat)

# axis=1 横向拼接
horizontal_concat = np.concatenate((matrix1, matrix2), axis=1)
print("\n横向拼接 (axis=1):")
print(horizontal_concat)

为了更直观地理解这个概念,让我们看一个 mermaid 图表来展示不同轴拼接的效果:

渲染错误: Mermaid 渲染失败: Parse error on line 2: ...] --> B[Matrix1
[[1,2],
 [3 -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'SUBROUTINESTART'

一维数组的拼接操作 💡

对于一维数组,拼接操作相对简单,因为只有一个轴(axis=0)。让我们探索一些具体的例子:

# 基本的一维数组拼接
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr3 = np.array([7, 8, 9])

# 连续拼接多个数组
result = np.concatenate((arr1, arr2, arr3))
print("连续拼接三个数组:", result)
# 输出: [1 2 3 4 5 6 7 8 9]

# 使用列表推导式进行批量拼接
arrays = [np.array([i, i+1]) for i in range(1, 10, 2)]
combined = np.concatenate(arrays)
print("批量拼接结果:", combined)
# 输出: [1 2 3 4 5 6 7 8 9 10]

需要注意的是,当处理一维数组时,只能使用 axis=0,因为一维数组只有一个维度:

# 尝试使用其他轴会导致错误
try:
    result = np.concatenate((arr1, arr2), axis=1)
except np.AxisError as e:
    print(f"错误信息: {e}")
    # 错误信息: axis 1 is out of bounds for array of dimension 1

二维数组的横向拼接 🔄

横向拼接是指将数组按列方向连接起来。这在处理表格数据时特别有用,比如合并不同的特征列。

# 创建示例数据
features1 = np.array([[1, 2], 
                      [3, 4], 
                      [5, 6]])
features2 = np.array([[7, 8], 
                      [9, 10], 
                      [11, 12]])
labels = np.array([[0], 
                   [1], 
                   [0]])

print("特征矩阵1:")
print(features1)
print("\n特征矩阵2:")
print(features2)
print("\n标签矩阵:")
print(labels)

# 横向拼接多个数组
combined_features = np.concatenate((features1, features2), axis=1)
print("\n横向拼接特征矩阵:")
print(combined_features)

# 同时拼接特征和标签
complete_data = np.concatenate((features1, features2, labels), axis=1)
print("\n完整的数据集:")
print(complete_data)

在实际应用中,横向拼接常用于数据预处理阶段,例如将不同的特征组合成一个完整的特征矩阵:

# 模拟真实场景:用户数据拼接
user_ids = np.array([[1001], [1002], [1003], [1004]])
ages = np.array([[25], [30], [35], [28]])
incomes = np.array([[50000], [75000], [90000], [60000]])
purchase_history = np.array([[3], [7], [12], [5]])

# 拼接所有用户特征
user_data = np.concatenate((user_ids, ages, incomes, purchase_history), axis=1)
print("用户数据汇总:")
print(user_data)
print("\n列含义: [用户ID, 年龄, 收入, 购买历史]")

二维数组的纵向拼接 ⬇️

纵向拼接是指将数组按行方向连接起来,这是最常见的拼接方式之一,特别是在合并来自不同来源但结构相同的数据时。

# 创建两个具有相同列数但不同行数的数组
batch1 = np.array([[1, 2, 3], 
                   [4, 5, 6]])
batch2 = np.array([[7, 8, 9], 
                   [10, 11, 12],
                   [13, 14, 15]])

print("批次1数据:")
print(batch1)
print("\n批次2数据:")
print(batch2)

# 纵向拼接
combined_batches = np.concatenate((batch1, batch2), axis=0)
print("\n纵向拼接后的完整数据:")
print(combined_batches)

纵向拼接的一个重要应用场景是在机器学习中合并训练数据:

# 模拟训练数据合并
train_set_1 = np.random.rand(100, 5)  # 100个样本,5个特征
train_set_2 = np.random.rand(150, 5)  # 150个样本,5个特征
train_set_3 = np.random.rand(75, 5)   # 75个样本,5个特征

# 合并所有训练数据
full_training_set = np.concatenate((train_set_1, train_set_2, train_set_3), axis=0)
print(f"合并后训练集形状: {full_training_set.shape}")
# 输出: 合并后训练集形状: (325, 5)

多维数组的拼接操作 📐

随着维度的增加,拼接操作变得更加灵活但也更加复杂。让我们看看三维数组的拼接:

# 创建三维数组
cube1 = np.array([[[1, 2], [3, 4]], 
                  [[5, 6], [7, 8]]])
cube2 = np.array([[[9, 10], [11, 12]], 
                  [[13, 14], [15, 16]]])

print("立方体1:")
print(cube1)
print("\n立方体2:")
print(cube2)

# axis=0: 在第一个维度上拼接
result_axis0 = np.concatenate((cube1, cube2), axis=0)
print(f"\naxis=0 拼接结果形状: {result_axis0.shape}")
print(result_axis0)

# axis=1: 在第二个维度上拼接
result_axis1 = np.concatenate((cube1, cube2), axis=1)
print(f"\naxis=1 拼接结果形状: {result_axis1.shape}")
print(result_axis1)

# axis=2: 在第三个维度上拼接
result_axis2 = np.concatenate((cube1, cube2), axis=2)
print(f"\naxis=2 拼接结果形状: {result_axis2.shape}")
print(result_axis2)

处理不兼容数组的拼接 ❌

在实际应用中,我们经常会遇到形状不匹配的数组。了解如何处理这些情况非常重要:

# 形状不匹配的情况
arr1 = np.array([[1, 2, 3], [4, 5, 6]])      # shape: (2, 3)
arr2 = np.array([[7, 8], [9, 10], [11, 12]]) # shape: (3, 2)

print("数组1形状:", arr1.shape)
print("数组2形状:", arr2.shape)

# 尝试直接拼接会失败
try:
    result = np.concatenate((arr1, arr2), axis=0)
except ValueError as e:
    print(f"拼接失败: {e}")

# 解决方案1: 调整数组形状使其兼容
# 方法1: 重新组织数据以匹配维度
arr2_transposed = arr2.T  # 转置使形状变为 (2, 3)
compatible_result = np.concatenate((arr1, arr2_transposed), axis=0)
print("\n调整后拼接结果:")
print(compatible_result)

# 解决方案2: 使用填充来使数组尺寸一致
def pad_arrays_for_concatenation(arrays, axis=0):
    """通过填充使数组可以拼接"""
    shapes = [arr.shape for arr in arrays]
    max_shape = list(shapes[0])
    
    # 找到每个维度的最大尺寸
    for shape in shapes[1:]:
        for i in range(len(shape)):
            if i < len(max_shape):
                max_shape[i] = max(max_shape[i], shape[i])
            else:
                max_shape.append(shape[i])
    
    # 填充所有数组到相同的最大尺寸
    padded_arrays = []
    for arr in arrays:
        padding = []
        for i in range(len(max_shape)):
            if i < len(arr.shape):
                padding.append((0, max_shape[i] - arr.shape[i]))
            else:
                padding.append((0, max_shape[i]))
        
        padded_arr = np.pad(arr, padding, mode='constant', constant_values=0)
        padded_arrays.append(padded_arr)
    
    return np.concatenate(padded_arrays, axis=axis)

# 示例:拼接不同形状的数组
irregular_arr1 = np.array([[1, 2], [3, 4]])
irregular_arr2 = np.array([[5, 6, 7]])

padded_result = pad_arrays_for_concatenation([irregular_arr1, irregular_arr2], axis=0)
print("\n填充后拼接结果:")
print(padded_result)

性能优化技巧 ⚡

在处理大型数组时,性能是一个重要的考虑因素。以下是一些优化拼接操作的技巧:

import time

# 创建大型数组进行性能测试
large_array1 = np.random.rand(10000, 1000)
large_array2 = np.random.rand(5000, 1000)

# 方法1: 直接拼接
start_time = time.time()
result1 = np.concatenate((large_array1, large_array2), axis=0)
time1 = time.time() - start_time
print(f"直接拼接耗时: {time1:.4f} 秒")

# 方法2: 预分配内存空间
start_time = time.time()
total_rows = large_array1.shape[0] + large_array2.shape[0]
result2 = np.empty((total_rows, large_array1.shape[1]))
result2[:large_array1.shape[0]] = large_array1
result2[large_array1.shape[0]:] = large_array2
time2 = time.time() - start_time
print(f"预分配内存拼接耗时: {time2:.4f} 秒")

# 对于已知最终大小的情况,预先创建目标数组可能更快

另一个重要的性能优化技巧是避免在循环中重复拼接数组:

# 不推荐的做法:在循环中反复拼接
def inefficient_concatenation(arrays):
    result = np.array([])
    for arr in arrays:
        result = np.concatenate((result, arr))
    return result

# 推荐的做法:收集所有数组然后一次性拼接
def efficient_concatenation(arrays):
    return np.concatenate(arrays)

# 性能对比
test_arrays = [np.random.rand(1000) for _ in range(100)]

# 测试低效方法
start_time = time.time()
result_slow = inefficient_concatenation(test_arrays)
time_slow = time.time() - start_time

# 测试高效方法
start_time = time.time()
result_fast = efficient_concatenation(test_arrays)
time_fast = time.time() - start_time

print(f"低效方法耗时: {time_slow:.4f} 秒")
print(f"高效方法耗时: {time_fast:.4f} 秒")
print(f"性能提升: {time_slow/time_fast:.2f} 倍")

实际应用场景 🌟

数据清洗和预处理

在数据分析项目中,经常需要合并来自不同源的数据:

# 模拟数据清洗场景
def merge_datasets(dataset_list):
    """
    合并多个数据集,自动处理缺失值和不一致的列
    """
    # 假设所有数据集都有相同的列结构
    # 实际应用中可能需要更多的预处理步骤
    
    # 过滤掉空的数据集
    valid_datasets = [ds for ds in dataset_list if ds.size > 0]
    
    if not valid_datasets:
        return np.array([])
    
    # 合并所有有效的数据集
    merged_data = np.concatenate(valid_datasets, axis=0)
    
    return merged_data

# 示例数据集
dataset1 = np.array([[1, 'A', 10.5], [2, 'B', 20.3], [3, 'C', 15.7]])
dataset2 = np.array([[4, 'D', 12.1], [5, 'E', 18.9]])
dataset3 = np.array([[6, 'F', 22.4]])

# 注意:这里为了简化示例,使用了字符串混合数组
# 在实际应用中,建议保持数值类型一致性

时间序列数据处理

在金融或物联网应用中,时间序列数据的拼接非常常见:

# 模拟股票价格数据拼接
def combine_stock_data(daily_data, weekly_data, monthly_data):
    """
    组合不同频率的股票数据
    """
    # 假设所有数据都已经被预处理为相同格式
    # 格式: [日期戳, 开盘价, 最高价, 最低价, 收盘价, 成交量]
    
    # 按时间顺序排序所有数据
    all_data = np.concatenate([daily_data, weekly_data, monthly_data], axis=0)
    
    # 按日期排序(假设第一列为日期戳)
    sorted_indices = np.argsort(all_data[:, 0])
    sorted_data = all_data[sorted_indices]
    
    return sorted_data

# 示例数据
daily_prices = np.array([
    [20230101, 100.5, 102.3, 99.8, 101.2, 1000000],
    [20230102, 101.2, 103.1, 100.5, 102.8, 1200000]
])

weekly_prices = np.array([
    [20230108, 102.8, 105.2, 101.5, 104.7, 8000000]
])

monthly_prices = np.array([
    [20230201, 104.7, 110.3, 103.2, 109.8, 25000000]
])

# 合并数据
combined_stock_data = combine_stock_data(daily_prices, weekly_prices, monthly_prices)
print("合并后的股票数据:")
print(combined_stock_data)

图像处理中的应用

在计算机视觉任务中,图像数据的拼接也很常见:

# 模拟图像通道拼接
def merge_image_channels(red_channel, green_channel, blue_channel):
    """
    将分离的RGB通道合并成彩色图像
    """
    # 确保所有通道形状一致
    assert red_channel.shape == green_channel.shape == blue_channel.shape
    
    # 将三个单通道图像合并成三通道图像
    # 假设输入是二维灰度图像,输出是三维彩色图像
    height, width = red_channel.shape
    rgb_image = np.zeros((height, width, 3))
    
    rgb_image[:, :, 0] = red_channel  # R通道
    rgb_image[:, :, 1] = green_channel  # G通道
    rgb_image[:, :, 2] = blue_channel  # B通道
    
    return rgb_image

# 或者使用 concatenate 直接拼接
def merge_channels_with_concatenate(channels):
    """
    使用 concatenate 合并图像通道
    """
    # 将所有通道扩展为三维数组然后拼接
    expanded_channels = [channel[:, :, np.newaxis] for channel in channels]
    return np.concatenate(expanded_channels, axis=2)

# 示例:模拟图像数据
red = np.random.randint(0, 256, (100, 100))
green = np.random.randint(0, 256, (100, 100))
blue = np.random.randint(0, 256, (100, 100))

# 合并通道
rgb_image = merge_channels_with_concatenate([red, green, blue])
print(f"合成图像形状: {rgb_image.shape}")  # 应该是 (100, 100, 3)

与其他拼接函数的比较 🆚

NumPy 提供了多种拼接函数,了解它们的区别很重要:

# 创建测试数据
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])

print("原始数组1:")
print(arr1)
print("\n原始数组2:")
print(arr2)

# 1. concatenate - 最通用的方法
concat_result = np.concatenate((arr1, arr2), axis=0)
print("\nconcatenate 结果:")
print(concat_result)

# 2. vstack - 垂直堆叠(等同于 axis=0 的 concatenate)
vstack_result = np.vstack((arr1, arr2))
print("\nvstack 结果:")
print(vstack_result)
print(f"vstack 和 concatenate 结果是否相同: {np.array_equal(concat_result, vstack_result)}")

# 3. hstack - 水平堆叠(等同于 axis=1 的 concatenate)
hstack_result = np.hstack((arr1, arr2))
print("\nhstack 结果:")
print(hstack_result)

# 4. dstack - 深度堆叠(沿第三轴堆叠)
dstack_result = np.dstack((arr1, arr2))
print("\ndstack 结果:")
print(dstack_result)
print(f"dstack 结果形状: {dstack_result.shape}")

# 5. column_stack - 列堆叠(对一维数组特别有用)
col1 = np.array([1, 2, 3])
col2 = np.array([4, 5, 6])
column_stack_result = np.column_stack((col1, col2))
print("\ncolumn_stack 结果:")
print(column_stack_result)

# 6. row_stack - 行堆叠(等同于 vstack)
row_stack_result = np.row_stack((arr1, arr2))
print("\nrow_stack 结果:")
print(row_stack_result)

每种函数都有其特定的用途:

  • concatenate: 最灵活,可以指定任意轴
  • vstack: 专门用于垂直堆叠
  • hstack: 专门用于水平堆叠
  • dstack: 专门用于深度堆叠
  • column_stack: 特别适合构建列数据
  • row_stack: 专门用于行堆叠

高级技巧和最佳实践 🎯

条件性拼接

有时我们需要根据条件来决定是否拼接某些数组:

def conditional_concatenate(arrays, conditions):
    """
    根据条件选择性地拼接数组
    """
    selected_arrays = [arr for arr, cond in zip(arrays, conditions) if cond]
    
    if not selected_arrays:
        return np.array([])
    
    return np.concatenate(selected_arrays, axis=0)

# 示例
data_arrays = [
    np.array([[1, 2], [3, 4]]),
    np.array([[5, 6], [7, 8]]),
    np.array([[9, 10], [11, 12]])
]

conditions = [True, False, True]  # 只选择第一个和第三个数组

result = conditional_concatenate(data_arrays, conditions)
print("条件拼接结果:")
print(result)

动态拼接策略

在处理不确定数量的数组时,动态拼接策略很有用:

def dynamic_concatenate(*arrays, axis=0, strategy='auto'):
    """
    动态拼接数组,支持不同的策略
    """
    if not arrays:
        return np.array([])
    
    if strategy == 'auto':
        # 自动检测最优策略
        if len(arrays) == 1:
            return arrays[0]
        elif len(arrays) <= 10:
            # 小数量直接拼接
            return np.concatenate(arrays, axis=axis)
        else:
            # 大数量分批处理
            batch_size = 100
            result = arrays[0]
            for i in range(1, len(arrays), batch_size):
                batch = arrays[i:i+batch_size]
                batch_result = np.concatenate(batch, axis=axis)
                result = np.concatenate((result, batch_result), axis=axis)
            return result
    
    return np.concatenate(arrays, axis=axis)

# 测试不同规模的数据
small_arrays = [np.random.rand(10, 5) for _ in range(5)]
medium_arrays = [np.random.rand(100, 50) for _ in range(50)]
large_arrays = [np.random.rand(1000, 100) for _ in range(200)]

print(f"小规模拼接结果形状: {dynamic_concatenate(*small_arrays).shape}")
print(f"中等规模拼接结果形状: {dynamic_concatenate(*medium_arrays).shape}")

内存友好的拼接

处理超大数组时,内存管理至关重要:

def memory_efficient_concatenate(array_generator, axis=0, chunk_size=1000):
    """
    内存友好的拼接方法,适用于大数据集
    """
    chunks = []
    current_chunk = []
    current_size = 0
    
    for array in array_generator:
        current_chunk.append(array)
        current_size += array.shape[axis] if axis < len(array.shape) else 1
        
        if current_size >= chunk_size:
            # 拼接当前块
            chunk = np.concatenate(current_chunk, axis=axis)
            chunks.append(chunk)
            current_chunk = []
            current_size = 0
    
    # 处理剩余的数据
    if current_chunk:
        chunk = np.concatenate(current_chunk, axis=axis)
        chunks.append(chunk)
    
    # 最终拼接所有块
    if not chunks:
        return np.array([])
    elif len(chunks) == 1:
        return chunks[0]
    else:
        return np.concatenate(chunks, axis=axis)

# 示例:生成器模式
def data_generator(num_arrays, array_shape):
    """模拟数据生成器"""
    for i in range(num_arrays):
        yield np.random.rand(*array_shape)

# 使用内存友好方式处理大量数据
result = memory_efficient_concatenate(
    data_generator(1000, (100, 50)), 
    axis=0, 
    chunk_size=50
)
print(f"内存友好拼接结果形状: {result.shape}")

错误处理和调试技巧 🔧

良好的错误处理是专业代码的重要组成部分:

def safe_concatenate(arrays, axis=0, fill_value=0):
    """
    安全的拼接函数,包含详细的错误处理
    """
    try:
        # 输入验证
        if not isinstance(arrays, (list, tuple)):
            raise TypeError("输入必须是数组列表或元组")
        
        if len(arrays) == 0:
            return np.array([])
        
        if len(arrays) == 1:
            return np.asarray(arrays[0])
        
        # 检查所有数组
        validated_arrays = []
        base_shape = None
        
        for i, arr in enumerate(arrays):
            arr = np.asarray(arr)
            
            if base_shape is None:
                base_shape = list(arr.shape)
            else:
                # 检查除拼接轴外的所有维度是否匹配
                if len(arr.shape) != len(base_shape):
                    raise ValueError(f"数组 {i} 的维度数 ({len(arr.shape)}) 与第一个数组 ({len(base_shape)}) 不匹配")
                
                for dim in range(len(base_shape)):
                    if dim != axis and base_shape[dim] != arr.shape[dim]:
                        raise ValueError(f"数组 {i} 在维度 {dim} 上的大小 ({arr.shape[dim]}) 与第一个数组 ({base_shape[dim]}) 不匹配")
            
            validated_arrays.append(arr)
        
        return np.concatenate(validated_arrays, axis=axis)
    
    except Exception as e:
        print(f"拼接过程中发生错误: {type(e).__name__}: {e}")
        raise

# 测试错误处理
try:
    # 正常情况
    normal_arrays = [np.array([[1, 2], [3, 4]]), np.array([[5, 6], [7, 8]])]
    result = safe_concatenate(normal_arrays, axis=0)
    print("正常拼接成功:")
    print(result)
    
    # 异常情况
    problematic_arrays = [np.array([[1, 2], [3, 4]]), np.array([[5, 6, 7], [7, 8, 9]])]
    result = safe_concatenate(problematic_arrays, axis=0)
except ValueError as e:
    print(f"捕获到预期错误: {e}")

实战案例分析 📊

让我们通过一个完整的实战案例来巩固所学知识:

class DataProcessor:
    """
    数据处理器类,演示各种拼接操作的实际应用
    """
    
    def __init__(self):
        self.processed_data = None
    
    def load_batch_data(self, file_paths):
        """
        模拟从多个文件加载数据批次
        """
        batches = []
        for path in file_paths:
            # 模拟数据加载
            batch_size = np.random.randint(50, 150)
            batch = np.random.rand(batch_size, 10)  # 10个特征
            batches.append(batch)
            print(f"从 {path} 加载了 {batch_size} 条记录")
        
        return batches
    
    def process_and_merge_batches(self, file_paths):
        """
        处理并合并多个数据批次
        """
        print("开始处理数据批次...")
        
        # 加载数据
        batches = self.load_batch_data(file_paths)
        
        # 数据预处理(示例:标准化)
        processed_batches = []
        for i, batch in enumerate(batches):
            # 简单的标准化处理
            mean_vals = np.mean(batch, axis=0)
            std_vals = np.std(batch, axis=0)
            # 避免除零错误
            std_vals[std_vals == 0] = 1
            normalized_batch = (batch - mean_vals) / std_vals
            processed_batches.append(normalized_batch)
            print(f"批次 {i+1} 处理完成")
        
        # 合并所有批次
        print("开始合并数据...")
        self.processed_data = np.concatenate(processed_batches, axis=0)
        print(f"合并完成!总数据量: {self.processed_data.shape[0]} 条记录")
        
        return self.processed_data
    
    def add_new_features(self, new_feature_data):
        """
        添加新特征到现有数据
        """
        if self.processed_data is None:
            raise ValueError("请先处理数据再添加新特征")
        
        # 确保新特征数据与现有数据行数匹配
        if new_feature_data.shape[0] != self.processed_data.shape[0]:
            raise ValueError(f"新特征数据行数 ({new_feature_data.shape[0]}) 与现有数据 ({self.processed_data.shape[0]}) 不匹配")
        
        # 横向拼接新特征
        self.processed_data = np.concatenate([self.processed_data, new_feature_data], axis=1)
        print(f"添加新特征完成!新数据形状: {self.processed_data.shape}")
        
        return self.processed_data
    
    def split_train_test(self, test_ratio=0.2):
        """
        分割训练集和测试集
        """
        if self.processed_data is None:
            raise ValueError("没有可用的数据进行分割")
        
        total_samples = self.processed_data.shape[0]
        test_size = int(total_samples * test_ratio)
        train_size = total_samples - test_size
        
        # 随机打乱数据
        indices = np.random.permutation(total_samples)
        train_indices = indices[:train_size]
        test_indices = indices[train_size:]
        
        train_data = self.processed_data[train_indices]
        test_data = self.processed_data[test_indices]
        
        print(f"数据分割完成: 训练集 {train_data.shape[0]} 条,测试集 {test_data.shape[0]} 条")
        
        return train_data, test_data

# 使用示例
processor = DataProcessor()

# 模拟文件路径
file_paths = ['data_batch_1.csv', 'data_batch_2.csv', 'data_batch_3.csv']

# 处理和合并数据
merged_data = processor.process_and_merge_batches(file_paths)

# 添加新特征
new_features = np.random.rand(merged_data.shape[0], 3)  # 3个新特征
enhanced_data = processor.add_new_features(new_features)

# 分割训练测试集
train_set, test_set = processor.split_train_test(test_ratio=0.25)

print(f"\n最终结果:")
print(f"- 合并数据形状: {merged_data.shape}")
print(f"- 增强数据形状: {enhanced_data.shape}")
print(f"- 训练集形状: {train_set.shape}")
print(f"- 测试集形状: {test_set.shape}")

总结与展望 🎉

通过这篇文章的学习,我们深入了解了 NumPy concatenate 函数的强大功能和灵活应用。从基础的一维数组拼接到复杂的多维数组操作,从简单的横向纵向拼接到高级的性能优化技巧,我们覆盖了数组拼接的各个方面。

关键要点回顾:

  1. 理解轴的概念:正确理解 axis 参数是掌握拼接操作的基础
  2. 选择合适的拼接方式:根据数据特点选择 concatenatevstackhstack 等函数
  3. 注意性能优化:避免在循环中反复拼接,合理预分配内存
  4. 处理边界情况:妥善处理形状不匹配、空数组等情况
  5. 实际应用导向:将理论知识应用到具体的数据处理场景中

NumPy 的数组拼接功能在数据科学、机器学习、图像处理等领域都有着广泛的应用。掌握这些技能不仅能够提高编程效率,还能让你更好地理解和处理复杂的数据结构。

如果你想进一步深入学习 NumPy 和相关技术,我推荐参考以下资源:

随着人工智能和大数据时代的到来,高效的数组操作能力变得越来越重要。希望本文能够帮助你在数据处理的道路上走得更远、更稳!🚀


🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/qq_41187124/article/details/157774853

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--