Numpy结构化数组,为多个y值相同的x,y对选择x值最小的x,y对

  • 本文关键字:结构化 选择 数组 Numpy python numpy
  • 更新时间 :
  • 英文 :


我有一个numpy结构化阵列

import numpy as np
arr1 = (np.array([2, 5, 8, 3, 10], dtype=np.int64),np.array([10, 10, 10, 8, 3], dtype=np.int64))
arr1_x = arr1[0]
arr1_y = arr1[1]
arr1_struct = np.empty(arr1_x.shape[0], dtype=[('x', int), ('y', int)])
arr1_struct["x"] = arr1_x
arr1_struct["y"] = arr1_y

正如您所看到的,在上面的结构化数组中,我有xy值。我需要做以下

  • 检查是否存在多个相同的y
  • 如果有,那么我只需要为y值保留一个x,y
  • 要保留的x值需要是与所讨论的y的值相对应的几个x数值中最小的1x
  • x,y对是唯一的,不重复

在上面的例子中,我需要保持

  • x=2和y=10(从三个y=10值中选择(
  • x=3和y=8
  • x=10和y=3

以下内容需要丢弃

  • x=5和y=10
  • x=8和y=10

numpy中有什么好的方法可以实现这一点吗?

首先,让我们稍微简化一下创建灰泥阵列的方式,没有其他原因,因为它正在磨我的齿轮:

data = np.stack(([2, 5, 8, 3, 10], [10, 10, 10, 8, 3]), axis=-1)
data = data.view(np.dtype([('x', int), ('y', int)])).ravel()

对数据进行排序并找到y的唯一值后,可以将np.minimum.reduceat应用于x:的结果段

data = data[np.argsort(data['y'])]
splits = np.r_[0, np.flatnonzero(np.diff(data['y'])) + 1]
x = np.minimum.reduceat(data['x'], splits)
y = data['y'][splits]

现在,您可以像以前一样重新创建阵列:

result = np.stack((x, y), axis=-1).view(data.dtype).ravel()

这就是np.uniquepd.DataFrame.groupby的工作原理。好的方面是,这种方法对重复配对不敏感。

另一种方法是使用np.lexsort,它可以同时对两列进行排序,从而使每个段的第一个元素最小:

data = data[np.lexsort((data['x'], data['y']))]
splits = np.r_[0, np.flatnonzero(np.diff(data['y'])) + 1]
result = data[splits]

这种方法比较干净,因为它允许您直接对数据进行索引。

也可以使用return_index=Truenp.diff计算替换为np.unique。这稍微贵一点,因为它对数组进行了两次排序:

data = data[np.lexsort((data['x'], data['y']))]
result = data[np.unique(data['y'], return_index=True)[1]]

最新更新