【发布时间】:2021-10-08 06:44:01
【问题描述】:
这是我目前正在做的,它可以工作,但有点麻烦:
x = np.matrix([[1, 1], [2, -3]])
xmax = x.flat[abs(x).argmax()]
【问题讨论】:
-
对我来说看起来很优雅...?是平缓还是什么?因为老实说,这看起来真的很不错。
这是我目前正在做的,它可以工作,但有点麻烦:
x = np.matrix([[1, 1], [2, -3]])
xmax = x.flat[abs(x).argmax()]
【问题讨论】:
您要查找的值必须是 x.max() 或 x.min(),以便您可以这样做
max(x.min(), x.max(), key=abs)
这类似于 aestrivex 的解决方案,但可能更具可读性?请注意,这将在x.min() 和x.max() 具有相同绝对值的情况下返回最小值,例如-5 和 5。如果您有偏好,只需相应地将输入订购到max。
【讨论】:
最紧凑的方式可能是:
x_max = np.abs(x).max()
默认情况下,.max() 方法直接对展平数组进行操作(取自NumPy documentation)。所以该运算寻找n维数组np.abs(x)的最大绝对值。
此外,它比问题的解决方案快 2000 倍以上。考虑到在 Дмитрий Пасько 的示例中应用的 IPython %time 魔术函数,我得到(在带有 Python 3.8 和 NumPy 1.19.1 的 MacBook Pro 2015 上):
x = np.random.rand(50000, 500) - 0.5
# numpy solution
x_max = np.abs(x).max()
"Wall time: 67.7 µs"
# question's solution
%time xmax = x[abs(x).argmax()]
"Wall time: 157 ms"
# Daniel's solution
%time xmax=x[np.unravel_index(abs(x).argmax(), x.shape)]
"Wall time: 88.9 µs"
# Дмитрий Пасько's solution
%time newdt = np.array([dt.min(),dt.max()])
... xmax = newdt.flat[abs(newdt).argmax()]
"Wall time: 26.7 ms"
【讨论】:
我正在寻找一种方法来获取沿指定轴的 N 维数组的最大绝对值的有符号值,这些答案都没有处理。所以,我整理了一个函数来完成它。没有承诺,但据我测试它是有效的:
def maxabs(a, axis=None):
"""Return slice of a, keeping only those values that are furthest away
from 0 along axis"""
maxa = a.max(axis=axis)
mina = a.min(axis=axis)
p = abs(maxa) > abs(mina) # bool, or indices where +ve values win
n = abs(mina) > abs(maxa) # bool, or indices where -ve values win
if axis == None:
if p: return maxa
else: return mina
shape = list(a.shape)
shape.pop(axis)
out = np.zeros(shape, dtype=a.dtype)
out[p] = maxa[p]
out[n] = mina[n]
return out
【讨论】:
这可以快速计算绝对最大值 - 以与 np.max 和 np.argmax 本身相同的方式尊重任意 axis 参数。
def absmaxND(a, axis=None):
amax = a.max(axis)
amin = a.min(axis)
return np.where(-amin > amax, amin, amax)
对于长数组,它比 a.flat[abs(a).argmax()] 快大约 2.5 倍,即使对于简单的情况 axis=None,因为它不会渲染原始大数组的 abs()。
【讨论】:
编辑:对不起,我的回答跑题了。正如 Ophion 指出的那样,这将返回索引,而不是值 - 您必须将 flat 与我的“xmax”(实际上是“xmaxInd”)一起使用才能获得正确的值。因此,我认为您的解决方案是最好的。
经过一番试验,我意识到你可以这样做:
x = np.matrix([[1,1], [2,-3]])
absX = abs(x)
xmax = argmax(absX)
似乎 numpy 允许您获取矩阵的abs 和argmax。多么方便!
timeit 检查:
def meth1():
x = np.matrix([[1,1],[2,-3]])
xmax = x.flat[abs(x).argmax()]
def meth2():
x = np.matrix([[1,1],[2,-3]])
xmax = argmax(abs(x))
t1 = timeit.Timer("meth1()","from __main__ import meth1")
t2 = timeit.Timer("meth2()","from __main__ import meth2")
mean(t1.repeat(1,100000)) 给Out[99]: 7.854323148727417
mean(t2.repeat(1,100000)) 给Out[98]: 7.7788529396057129
所以meth2() 稍微快一点。可能是因为它不涉及调用flat。
【讨论】:
flat。
我唯一能想到的,看起来更糟糕的是:
xmax=x[np.unravel_index(abs(x).argmax(), x.shape)]
【讨论】:
我用过
dt = np.random.rand(50000,500)-0.5
# ur
xmax = dt.flat[abs(dt).argmax()] #230 ms
# new
newdt = np.array([dt.min(),dt.max()]) # 56ms
xmax = newdt.flat[abs(newdt).argmax()] # 4ms
几乎快 4 倍(60 毫秒对 230 毫秒)!!
【讨论】:
请原谅死灵,但我似乎无法评论 JoeCondron 的回答。
我喜欢:
max(x.min(), x.max(), key=abs)
但我相信它可以进一步简化:
max(x, key=abs)
似乎对我有用(或非一维):
max(x.flat, key=abs)
【讨论】:
我认为这是一种非常简单的方法,如果代码可读性是您最关心的问题,它可能会稍微好一些。但实际上,您的方式同样优雅。
np.min(x) if np.max(abs(x)) == abs(np.min(x)) else np.max(x)
【讨论】: