Python 矩形网格上的Numpy叉积
我有两个numpy数组,其中包含2d向量:Python 矩形网格上的Numpy叉积,python,numpy,Python,Numpy,我有两个numpy数组,其中包含2d向量: import numpy as np a = np.array([[ 0.999875, 0.015836], [ 0.997443, 0.071463], [ 0.686554, 0.727078], [ 0.93322 , 0.359305]]) b = np.array([[ 0.7219 , 0.691997], [ 0
import numpy as np
a = np.array([[ 0.999875, 0.015836],
[ 0.997443, 0.071463],
[ 0.686554, 0.727078],
[ 0.93322 , 0.359305]])
b = np.array([[ 0.7219 , 0.691997],
[ 0.313656, 0.949537],
[ 0.507926, 0.861401],
[ 0.818131, 0.575031],
[ 0.117956, 0.993019]])
如您所见,a.shape
是(4,2),而b.shape
是(5,2)
现在,我可以得到我想要的结果:
In [441]: np.array([np.cross(av, bv) for bv in b for av in a]).reshape(5, 4)
Out[441]:
array([[ 0.680478, 0.638638, -0.049784, 0.386403],
[ 0.944451, 0.924694, 0.423856, 0.773429],
[ 0.85325 , 0.8229 , 0.222097, 0.621377],
[ 0.562003, 0.515094, -0.200055, 0.242672],
[ 0.991027, 0.982051, 0.595998, 0.884323]])
我的问题是:有什么更“numpythonic”的方式来获得上述内容(即没有嵌套列表理解)?我尝试了我能想到的np.cross()
的每一种组合,通常得到如下结果:
In [438]: np.cross(a, b.T, axisa=1, axisb=0)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-438-363c0765a7f9> in <module>()
----> 1 np.cross(a, b.T, axisa=1, axisb=0)
D:\users\ae4652t\Python27\lib\site-packages\numpy\core\numeric.p<snipped>
1242 if a.shape[0] == 2:
1243 if (b.shape[0] == 2):
-> 1244 cp = a[0]*b[1] - a[1]*b[0]
1245 if cp.ndim == 0:
1246 return cp
ValueError: operands could not be broadcast together with shapes (4) (5)
[438]中的:np.cross(a,b.T,axisa=1,axisb=0)
---------------------------------------------------------------------------
ValueError回溯(最近一次调用上次)
在()
---->1 np.交叉(a,b.T,axisa=1,axisb=0)
D:\users\ae4652t\Python27\lib\site packages\numpy\core\numeric.p
1242如果a.shape[0]==2:
1243如果(b.形状[0]==2):
->1244 cp=a[0]*b[1]-a[1]*b[0]
1245如果cp.ndim==0:
1246返回cp
ValueError:操作数无法与形状(4)(5)一起广播
我在这方面想得更多了
>>> a
array([[ 0.999875, 0.015836],
[ 0.997443, 0.071463],
[ 0.686554, 0.727078],
[ 0.93322 , 0.359305]])
>>> b
array([[ 0.7219 , 0.691997],
[ 0.313656, 0.949537],
[ 0.507926, 0.861401],
[ 0.818131, 0.575031],
[ 0.117956, 0.993019]])
>>> c = np.tile(a, (b.shape[0], 1))
>>> d = np.repeat(b, a.shape[0], axis=0)
>>> np.cross(c, d).reshape(5,4)
array([[ 0.68047849, 0.63863842, -0.0497843 , 0.38640316],
[ 0.94445125, 0.92469424, 0.42385605, 0.77342875],
[ 0.85324981, 0.82290048, 0.22209648, 0.62137629],
[ 0.5620032 , 0.51509455, -0.20005522, 0.24267187],
[ 0.99102692, 0.98205036, 0.59599795, 0.88432301]])
一些时间安排:
import timeit
s="""
import numpy as np
a=np.random.random(100).reshape(-1, 2)
b=np.random.random(1000).reshape(-1, 2)
"""
ophion="""
np.cross(np.tile(a,(b.shape[0],1)),np.repeat(b,a.shape[0],axis=0))"""
subnivean="""
np.array([np.cross(av, bv) for bv in b for av in a]).reshape(b.shape[0], a.shape[0])"""
DSM="""
np.outer(b[:,1], a[:,0]) - np.outer(b[:,0], a[:,1])"""
Jamie="""
np.cross(a[None], b[:, None, :])"""
h=timeit.timeit(subnivean,setup=s,number=10)
m=timeit.timeit(ophion,setup=s,number=10)
d=timeit.timeit(DSM,setup=s,number=10)
j=timeit.timeit(Jamie,setup=s,number=10)
print "subnivean's method took",h,'seconds.'
print "Ophion's method took",m,'seconds.'
print "DSM's method took",d,'seconds.'
"
subnivean's method took 1.99507117271 seconds.
Ophion's method took 0.0149450302124 seconds.
DSM's method took 0.0040500164032 seconds.
Jamie's method took 0.00390195846558 seconds."
对于a=10和b=100的长度:
"
subnivean's method took 0.0217308998108 seconds.
Ophion's method took 0.00046181678772 seconds.
DSM's method took 0.000531911849976 seconds.
Jamie's method took 0.000334024429321 seconds."
嗯,你再次切换了叉积的顺序,如果你想要(5,4)或(4,5),两个答案都会显示出来。我还没有计时我的代码,但我几乎可以肯定,没有比这更简单的方法了:
>>> np.cross(a[None], b[:, None])
array([[ 0.68047849, 0.63863842, -0.0497843 , 0.38640316],
[ 0.94445125, 0.92469424, 0.42385605, 0.77342875],
[ 0.85324981, 0.82290048, 0.22209648, 0.62137629],
[ 0.5620032 , 0.51509455, -0.20005522, 0.24267187],
[ 0.99102692, 0.98205036, 0.59599795, 0.88432301]])
答案总是…你是在尝试内积吗?你所做的不是一个交叉积。我想我在一个4 x 5的网格上做了20个交叉积,不是吗?这就是我在列表理解中调用的函数。我知道你在做什么,除非这些数组非常大,否则可能不值得对其进行优化。@EOL我同意,我现在非常好奇是否有一种方法可以比我建议的方法更有效地按行获取两个数组之间的所有组合。我的数组还不是很大;只是想做好准备。当我使用numpy时,每当我看到
的时,我都会感到有点不舒服:-)谢谢你提供了所有的答案w/timings.Updated以满足你的需要。嘿,这不公平:当我计时时,你不仅仅是在测试我的解决方案(使用np.outer
),你还包括了listcomp
行,这是OP的解决方案,我加入它只是为了检查答案。啊,我很抱歉-现在更新。这样更好。(^)+1用于包括定时代码。[也就是说,我完全同意,除非OP真的需要,否则可能不值得对此进行优化。];)在这类事情中,时间通常是最后的决定。我真的很喜欢你的回答。。。外部产品的伟大使用!美好的这应该是公认的答案。虽然“总是”有点夸张——但在很多情况下,广播会导致不实用的大中间阵列。更新了我的文章中的计时!因为我以前从未见过[None]的用法,所以它和重塑(1,-1)有什么区别吗?谢谢,这正是我想要的。我可能建议用np.newaxis
代替None
,但我不确定它读起来是否更清楚。谢谢你的链接;我将再次学习广播。@Ophion我过去总是按照您的建议进行显式重塑,但最近我倾向于使用无
进行切片,因为它通常允许更紧凑的代码。这也是我选择None
而不是np.newaxis
的原因。