numpy根据值的大小来拆分数组,并新建一个轴

在numpy中,常规的数据切片,根据轴来进行数据切分等,都很方便。但,如果要根据矩阵中的值来切分数组,并新建一个维度,这个还是有点麻烦。记录过程如下:

有这么一个数组:

import numpy as np

rs = [
      [1, 23, 87],
      [2, 34, 98],
      [3, 32, 73],
      [4, 76, 74],
      [5, 54, 11],
      [6, 65, 76],
      [7, 87, 29],
      [8, 43, 62],
      [9, 54, 36]
      ]

ndarray = np.array(rs)

我希望,根据第1列的值,增加一个轴,最终拆分成 【x<=3】【3<x<=6】【6<x】三个区间,然后再汇总这三个区间的合计值。

我先切出矩阵的第一列,其他维度不变:

filter_nda = ndarray[:, [0]]

filter_nda
array([[1],
       [2],
       [3],
       [4],
       [5],
       [6],
       [7],
       [8],
       [9]])

做筛选索引:

where_1 = np.where(filter_nda<=3) 

Out: (array([0, 1, 2]), array([0, 0, 0]))


# 当 where 中有多个条件表达式时,每个表达式都必须用括号括起来
where_2 = np.where((filter_nda>3) & (filter_nda<=6)) 

out:(array([3, 4, 5]), array([0, 0, 0]))

where_3 = np.where(filter_nda>6)

Out: (array([6, 7, 8]), array([0, 0, 0]))

三个区间,所以有三个表达式。看输出,(array([6, 7, 8]), array([0, 0, 0])),可以看到这是numpy中的整数数组索引,代表了三个坐标位置。

为什么第二个数组都是[0,0,0],因为索引矩阵只有一列,所以这个索引不重要,重要的是前面的其他维度的索引值。

下一步,就是根据这三个索引数组,构建三个新的矩阵,因为,引入了一个新的维度,所以,新的矩阵要多出一维。

section_1 = np.zeros(ndarray.shape, dtype=np.int32)
section_1 = np.expand_dims(section_1, 0) #在 0 轴插入一个新维度

section_2 = np.zeros(ndarray.shape, dtype=np.int32)
section_2 = np.expand_dims(section_2, 0) #在 0 轴插入一个新维度

section_3 = np.zeros(ndarray.shape, dtype=np.int32)
section_3 = np.expand_dims(section_3, 0) #在 0 轴插入一个新维度

对比一下两个矩阵的 shape

ndarray.shape
Out[165]: (9, 3)

section_1.shape
Out[166]: (1, 9, 3)

好了,下面有一个有意思的操作,根据其他维度的索引值,把所有数据复制到新的矩阵

for y in range(3): # 原矩阵的第1轴有3个数据
    for x in range(len(where_1[0])): # 原矩阵的第0轴的索引数组
        section_1[0, where_1[0][x], y] = ndarray[where_1[0][x], y] #复制数据

因为,使用 ndarray[where_1] 直接把数据切出来,会丧失维度信息,降维成了一维数组。要保持维度结构,只好手动复制数据了。看一下结果:

section_1
Out[170]: 
array([[[ 1, 23, 87],
        [ 2, 34, 98],
        [ 3, 32, 73],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0]]], dtype=int32)

果然,只复制出第一个区间的数据。同样流程,生成第二、三区间的矩阵(section_2, section_3)

剩下的就简单了。把三个矩阵,延着第 0 轴,连接起来就可以了。

new_ndarray = np.concatenate([section_1, section_2, section_3], axis=0)

看一下,因为在原来的结构上,新增一个维度,数据还是那些数据。多出的 0 是必要的,因为维度结构被保留了。可以看到,随着维度的增加,存贮空间是指数级增长的。

new_ndarray
Out[187]: 
array([[[ 1, 23, 87],
        [ 2, 34, 98],
        [ 3, 32, 73],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0]],

       [[ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 4, 76, 74],
        [ 5, 54, 11],
        [ 6, 65, 76],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0]],

       [[ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 0,  0,  0],
        [ 7, 87, 29],
        [ 8, 43, 62],
        [ 9, 54, 36]]], dtype=int32)

好,我们按新的维度,延着第 1 轴来汇总一下数据:

np.sum(new_ndarray, axis=1)
Out[189]: 
array([[  6,  89, 258],
       [ 15, 195, 161],
       [ 24, 184, 127]])

三行,分别是三个区间的汇总值。

这个需求,有点意思。花了一些时间。

更多的维度也是一样的,在代码上要做自适应的处理,这里演示的是单步手动执行的代码。自适应多维的矩阵的代码会更复杂一些。代码

如果有谁有其他的更好方法,请务必告知我。深表感谢。

### 使用 NumPy 拆分数组的方法 #### 方法一:水平拆分 `hsplit` 当需要将多维数组沿着水平(即行的方向)进行拆分时,`np.hsplit()` 函数是非常有效的工具。此函数接受两个参数:要被分割的数组以及指示切割次数或位置的整数或表。 ```python import numpy as np arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]]) newarr = np.hsplit(arr, 3) print(newarr) ``` 上述代码会创建一个新的三维数组集合,每个子数组包含了原矩阵中的部分[^2]。 #### 方法二:通用拆分 `split` 对于更灵活的需求,比如按照指定索引处切片或将整个数组均匀分配给若干个新数组的情况,则应考虑使用更为通用的 `np.split()` 函数。该函数同样适用于任何维度的数据结构,允许用户自定义划分方式。 ```python import numpy as np # 创建一个简单的二维数组作为演示对象 data = np.arange(16).reshape((4, 4)) # 均匀地将其划分为四个相同大小的一维向量 result = np.split(data.flatten(), 4) print(result) ``` 这里展示了如何先展平原始数组再做均等分割的操作[^3]。 #### 方法三:垂直拆分 `vsplit` 如果目标是在竖直方向上对数组实施分区——也就是按照行来进行分离的话,那么应该选用 `np.vsplit()` 来完成这项工作。这与前面提到过的 `hsplit` 类似,只不过作用于不同的线上而已。 ```python import numpy as np matrix = np.random.rand(6, 3) * 100 sub_matrices = np.vsplit(matrix, 3) for i, sub_matrix in enumerate(sub_matrices): print(f'Sub-matrix {i}:') print(sub_matrix) ``` 这段脚本实现了随机生成的一个 \(6 \times 3\) 的浮点型数表单被切成三个独立的小表格的过程。 #### 组合应用实例 有时可能还会遇到更加复杂的场景,例如既要在横向也要在纵向执行多次连续性的切割动作;此时可以通过组合运用这些基础命令来达成目的: ```python import numpy as np original_array = np.arange(24).reshape((6, 4)) horizontal_parts = np.hsplit(original_array, 2) final_result = [] for part in horizontal_parts: vertical_slices = np.vsplit(part, 3) final_result.extend(vertical_slices) for idx, slice_ in enumerate(final_result): print(f'Final Slice #{idx}:\n{slice_}') ``` 以上程序片段先是把输入的大矩形区域依据宽度劈成两半,接着又分别在这两份基础上进一步细分成更多小块[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值