使用Numpy.where从基于另一个数组的数组中获取Max / Min

时间:2017-02-07 19:08:15

标签: python arrays numpy

从这开始:

import numpy as np
x = np.array([0,   2,  8,  9,  4,    1, 12,  4, 33, 11,    5,  3 ])
y = np.array(['', '', '', '', '', 'yo', '', '', '', '', 'yo', '' ])
i = np.array([0,   1,  2,  3,  4,    5,  6,  7,  8,  9,   10, 11 ])
print np.amax(x[:3] )         
print np.amin(x[:3] )        

尝试使用numpy.where获取前三个项目的最大值或最小值。所以,本质上是试图使用数组中的“索引” np.where。如果有更高性能的方法,请显示。

对此进行了尝试:

np.where(y == "yo", np.amax(x[:3] ) ,"")

结果(为什么它返回一个字符串?):

array(['', '', '', '', '', '8', '', '', '', '', '8', ''], 
      dtype='|S21')

想:

 array(['', '', '', '', '', 9, '', '', '', '', 33, ''], 
      dtype='|S21')

3 个答案:

答案 0 :(得分:2)

首先看一下where的更简单版本,它找到索引:

In [266]: np.where(y=='yo')
Out[266]: (array([ 5, 10], dtype=int32),)

显然,你想要y的所有版本,但用yo中的某个值替换x

In [267]: np.where(y=='yo',x,y)
Out[267]: 
array(['', '', '', '', '', '1', '', '', '', '', '5', ''], 
      dtype='<U11')

y是字符串类型,由于''无法转换为数字,因此数字将转换为字符串。

现在,如果y是对象dtype:

In [268]: y = np.array(['', '', '', '', '', 'yo', '', '', '', '', 'yo', '' ],object)
In [269]: np.where(y=='yo')
Out[269]: (array([ 5, 10], dtype=int32),)
In [270]: np.where(y=='yo',x,y)
Out[270]: array(['', '', '', '', '', 1, '', '', '', '', 5, ''], dtype=object)

替换也是对象dtype,可以混合使用数字和字符串。

在此用法中,所有3个术语的长度相同。在您的使用中,xy将替换为标量

In [271]: np.max(x[:3])
Out[271]: 8
In [272]: np.where(y=='yo',8, '')
Out[272]: 
array(['', '', '', '', '', '8', '', '', '', '', '8', ''], 
      dtype='<U11')
In [273]: np.where(y=='yo',8, y)
Out[273]: array(['', '', '', '', '', 8, '', '', '', '', 8, ''], dtype=object)

要插入933,您已经找到了收集前3项最大值的某种方法,即运行或滚动最大值。 where本身无济于事。

accumulate近似于此(这是cumsum的'最大'版本)

In [276]: xm=np.maximum.accumulate(x)
In [277]: xm
Out[277]: array([ 0,  2,  8,  9,  9,  9, 12, 12, 33, 33, 33, 33], dtype=int32)
In [278]: np.where(y=='yo',xm, y)
Out[278]: array(['', '', '', '', '', 9, '', '', '', '', 33, ''], dtype=object)

xm不是前三个值的最大值,而是所有先前值的最大值。在这种情况下是相同的,但一般情况下它不会。对于此x,最后一个值

是不同的

这是获得前3个最大值的一种方法,无可否认有点粗略(具有列表理解力):

In [305]: x1=np.concatenate(([0,0],x))
In [306]: xm = [max(x1[i:i+3]) for i in range(0,len(x1))][:len(x)]
In [307]: xm
Out[307]: [0, 2, 8, 9, 9, 9, 12, 12, 33, 33, 33, 11]
In [308]: np.where(y=='yo',xm, y)
Out[308]: array(['', '', '', '', '', 9, '', '', '', '', 33, ''], dtype=object)

使用as_strided(改编自Numpy: Matrix Array Shift / Insert by Index

的滑动窗口
In [317]: xm=np.lib.stride_tricks.as_strided(x1[::-1],shape=(3,12),strides=(-4,-4))
In [318]: xm
Out[318]: 
array([[ 3,  5, 11, 33,  4, 12,  1,  4,  9,  8,  2,  0],
       [ 5, 11, 33,  4, 12,  1,  4,  9,  8,  2,  0,  0],
       [11, 33,  4, 12,  1,  4,  9,  8,  2,  0,  0,  0]])
In [319]: xm.max(axis=0)
Out[319]: array([11, 33, 33, 33, 12, 12,  9,  9,  9,  8,  2,  0])
In [320]: xm = xm.max(axis=0)[::-1]
In [321]: xm
Out[321]: array([ 0,  2,  8,  9,  9,  9, 12, 12, 33, 33, 33, 11])

使用Paul Panzer的想法只有几个yo

In [29]: idx=np.where(y=='yo')
In [30]: idx
Out[30]: (array([ 5, 10], dtype=int32),)

In [32]: xm = [max(x[i-3:i]) for i in idx[0]]
In [33]: xm
Out[33]: [9, 33]
In [34]: y[idx]=xm
In [35]: y
Out[35]: array(['', '', '', '', '', 9, '', '', '', '', 33, ''], dtype=object)

如果前3个元素中可能出现yo,我们需要使用以下内容优化xm

xm = [max(x[max(i-3,0):i+1]) if i>0 else x[i] for i in idx[0]]

否则我们会因尝试max([])而感到错误。

答案 1 :(得分:0)

“我想要的”项目,我担心你不能拥有,因为你不能在字符串dtype数组中包含数字。您正在使用它的形式where将其最后两个参数“混合”到一个数组中。为此,它必须选择一个dtype。由于

,它将用于字符串
>>> np.can_cast(str, int)
False
>>> np.can_cast(int, str)
True

所以str是两个参数'dtypes / types之一,可以容纳两个参数的值。

除了数据类型之外,您可能希望查看scipy.ndimage.maximum_filter

>>> scipy.ndimage.maximum_filter(x, 3)
array([ 2,  8,  9,  9,  9, 12, 12, 33, 33, 33, 11,  5])

您可能需要修改偏移量以满足您的要求。

答案 2 :(得分:0)

不确定我理解你想要什么,但这有助于:

x = np.sort(x)
sel = np.where(y=="yo")[0]
y[sel] = x[-len(sel):]