You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简化Numpy中按0轴唯一值归集1轴对应元素的代码?

问题描述

现有Numpy矩阵:

import numpy as np
bins = np.array([[2076., -861.84471079],
       [2076., -858.23866597],
       [2076., -861.84471079],
       ...,
       [9757., 1847.33889178],
       [9757., 1830.39082856],
       [9757., -932.14347751]])

需求:按0轴的每个唯一值,收集对应的1轴所有元素,示例输出如下:

bins = np.array([[2076., [-861.84471079, -858.2386, -861.84471]],
       [9757., [1847.33889178, 1830.3908, -932.14]]])

当前实现代码:

bins = points_OYZ[points_OYZ[:, 0].argsort()]

vals, idx_start, count = np.unique(bins[:, 0], return_counts=True, return_index=True)

binarize_matrix = np.split(bins, idx_start[1:])

q = []
for i in binarize_matrix:
    min_index = np.argmin(i[:, 1])
    q.append(i[min_index])

希望得到更简洁的实现方式。

简洁实现方案

方案1:纯Numpy实现(无额外依赖)

利用np.unique的return_inverse参数快速分组,既可以实现收集1轴元素的需求,也能同时获取每组中1轴最小值对应的行:

# 获取唯一值及逆索引(用于分组)
vals, inv_idx = np.unique(bins[:, 0], return_inverse=True)

# 仅收集每个唯一值对应的1轴所有元素
result = np.array([[val, bins[inv_idx == i, 1]] for i, val in enumerate(vals)], dtype=object)

# 如果要同时获取每组中1轴最小值对应的完整行
min_rows = np.array([bins[inv_idx == i][np.argmin(bins[inv_idx == i, 1])] for i, val in enumerate(vals)])

方案2:用Pandas简化代码

如果项目允许引入Pandas,代码会更直观简洁:

import pandas as pd

# 转换为DataFrame方便分组
df = pd.DataFrame(bins, columns=['key', 'value'])

# 收集每个key对应的所有value,转换为需求的numpy数组格式
grouped_result = df.groupby('key')['value'].apply(list).reset_index().to_numpy(dtype=object)

# 如果要获取每组中value最小的行
min_row_result = df.loc[df.groupby('key')['value'].idxmin()].to_numpy()

原代码的精简优化

如果想基于原有思路简化,用列表推导式替代显式循环:

bins = points_OYZ[points_OYZ[:, 0].argsort()]
vals, idx_start = np.unique(bins[:, 0], return_index=True)
# 用zip拼接分组的起始和结束索引,直接生成结果
q = [bins[s:e][np.argmin(bins[s:e, 1])] for s, e in zip(idx_start, np.append(idx_start[1:], len(bins)))]

内容的提问来源于stack exchange,提问作者Opacho And

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 11:42:16