Python 将3参数函数应用于三维numpy数组
我有一个形状为(2133,3,3)的3D numpy数组。基本上,这是一个包含2133个列表和三个3D点的列表。此外,我还有一个函数,它获取三个3D点并返回一个3D点,Python 将3参数函数应用于三维numpy数组,python,numpy,Python,Numpy,我有一个形状为(2133,3,3)的3D numpy数组。基本上,这是一个包含2133个列表和三个3D点的列表。此外,我还有一个函数,它获取三个3D点并返回一个3D点,x=f(a,b,c),其中a,b,c,x numpy数组长度为3。现在我想将f应用于A,这样输出就是一个shape数组(2133,3)。所以类似于numpy.array([f(*A[0]),…,f(*A[2132]) 我尝试了numpy。沿_轴应用_和numpy。矢量化,但没有成功 更确切地说,我考虑的函数是: def f(a,
x=f(a,b,c)
,其中a,b,c,x numpy数组长度为3。现在我想将f应用于A,这样输出就是一个shape数组(2133,3)。所以类似于numpy.array([f(*A[0]),…,f(*A[2132])
我尝试了numpy。沿_轴应用_
和numpy。矢量化
,但没有成功
更确切地说,我考虑的函数是:
def f(a, b, c, r1, r2=None, r3=None):
a = np.asarray(a)
b = np.asarray(b)
c = np.asarray(c)
if np.linalg.matrix_rank(np.matrix([a, b, c])) != 3:
# raise ValueError('The points are not collinear.')
return None
a, b, c, = sort_triple(a, b, c)
if any(r is None for r in (r2, r3)):
r2, r3 = (r1, r1)
ex = (b - a) / (np.linalg.norm(b - a))
i = np.dot(ex, c - a)
ey = (c - a - i*ex) / (np.linalg.norm(c - a - i*ex))
ez = np.cross(ex, ey)
d = np.linalg.norm(b - a)
j = np.dot(ey, c - a)
x = (pow(r1, 2) - pow(r2, 2) + pow(d, 2)) / (2 * d)
y = ((pow(r1, 2) - pow(r3, 2) + pow(i, 2) + pow(j, 2)) / (2*j)) - ((i/j)*x)
z_square = pow(r1, 2) - pow(x, 2) - pow(y, 2)
if z_square >= 0:
z = np.sqrt(z_square)
intersection = a + x * ex + y*ey + z*ez
return intersection
A = np.array([[[131.83, 25.2, 0.52], [131.51, 22.54, 0.52],[133.65, 23.65, 0.52]], [[13.02, 86.98, 0.52], [61.02, 87.12, 0.52],[129.05, 87.32, 0.52]]])
r1 = 1.7115
这很好(在注释掉sort\u triple
之后):
制作:
[array([ 132.21182324, 23.80481826, 1.43482849]), None]
这看起来像是一行产生了一个(3,)另一个数组出现了某种问题,并产生了None
。我不知道None
是否是由于删除了排序。但在任何情况下,将数组和None
的混合返回到一个数组将是一个问题。如果res
的所有项都匹配数组,我们可以stack
将它们返回转换为二维数组
有一些方法可以获得适度的速度提升(与列表理解相比)。但是对于这样一个复杂的函数,在函数中花费的时间(称为2000次)占迭代机制花费的时间的主导地位
由于您在第1维上迭代,并传递其他2维(作为3个数组),因此此显式循环比矢量化
、frompyfunc
或沿..
应用要容易得多
为了节省大量时间,您必须编写
f()
来直接使用3d阵列。多亏了@jdehesa的大力帮助,我能够生成一个替代@hpaulj给出的解决方案。我不确定此解决方案是否是最优雅的解决方案,但迄今为止它仍然有效。欢迎评论
def sort_triple(a, b, c):
pts = np.stack((a, b, c), axis=1)
xSorted = pts[np.arange(pts.shape[0])[:, None], np.argsort(pts[:, :, 0])]
orientation = np.cross(xSorted[:, 1] - xSorted[:, 0], xSorted[:, 2] -
xSorted[:, 0])[:, 2] >= 0
xSorted_flipped = np.stack((xSorted[:, 0], xSorted[:, 2], xSorted[:, 1]),
axis=1)
xSorted = np.where(orientation[:, np.newaxis, np.newaxis], xSorted,
xSorted_flipped)
return map(np.squeeze, np.split(xSorted, 3, axis=1))
def f(A, r1, r2=None, r3=None):
a, b, c = map(np.squeeze, np.split(A, 3, axis=1))
a, b, c = sort_triple(a, b, c)
if any(r is None for r in (r2, r3)):
r2, r3 = (r1, r1)
ex = (b - a) / (np.linalg.norm(b - a, axis=1))[:, np.newaxis]
i = inner1d(ex, (c - a))
ey = ((c - a - i[:, np.newaxis]*ex) /
(np.linalg.norm(c - a - i[:, np.newaxis]*ex, axis=1))[:, np.newaxis])
ez = np.cross(ex, ey)
d = np.linalg.norm(b - a, axis=1)
j = inner1d(ey, c - a)
x = (np.square(r1) - np.square(r2) + np.square(d)) / (2 * d)
y = ((np.square(r1) - np.square(r3) + np.square(i) + np.square(j)) / (2*j) -
i/j*x)
z_square = np.square(r1) - np.square(x) - np.square(y)
mask = z_square < 0
z_square[mask] *= 0
z = np.sqrt(z_square)
z[mask] = np.nan
intersection = (a + x[:, np.newaxis] * ex + y[:, np.newaxis] * ey +
z[:, np.newaxis] * ez)
return intersection
def sort_三重(a、b、c):
pts=np.堆栈(a、b、c),轴=1)
xSorted=pts[np.arange(pts.shape[0])[:,None],np.argsort(pts[:,:,0])]
方向=np.cross(xSorted[:,1]-xSorted[:,0],xSorted[:,2]-
X排序[:,0])[:,2]>=0
xSorted_fliped=np.stack((xSorted[:,0],xSorted[:,2],xSorted[:,1]),
轴=1)
xSorted=np.where(方向[:,np.newaxis,np.newaxis],xSorted,
X排序(翻转)
返回映射(np.Squence,np.split(X排序,3,轴=1))
def f(A、r1、r2=无,r3=无):
a、 b,c=映射(np.挤压,np.分裂(a,3,轴=1))
a、 b,c=排序三(a,b,c)
如果有(对于(r2,r3)中的r,r为无):
r2,r3=(r1,r1)
ex=(b-a)/(np.linalg.norm(b-a,axis=1))[:,np.newaxis]
i=内部1d(例如,(c-a))
ey=((c-a-i[:,np.newaxis]*ex)/
(np.linalg.norm(c-a-i[:,np.newaxis]*ex,axis=1))[:,np.newaxis])
ez=np.交叉(例如,ey)
d=np.linalg.norm(b-a,轴=1)
j=1d(ey,c-a)
x=(np平方(r1)-np平方(r2)+np平方(d))/(2*d)
y=((np.平方(r1)-np.平方(r3)+np.平方(i)+np.平方(j))/(2*j)-
i/j*x)
z_平方=np.平方(r1)-np.平方(x)-np.平方(y)
掩码=z_平方<0
z_平方[掩码]*=0
z=np.sqrt(z_平方)
z[mask]=np.nan
交点=(a+x[:,np.newaxis]*ex+y[:,np.newaxis]*ey+
z[:,np.newaxis]*ez)
返回交叉口
可能每个函数中的
map
部分可以做得更好。也可能过度使用np.newaxis
看看你用np尝试了什么。矢量化和np.apply_沿_轴
会很有帮助。另外,函数f到底有什么作用?你可以用矢量化的版本替换它。@user2699我提供了函数f
。我认为np.apply\u沿轴
的问题在于它沿给定轴应用于1D切片。np.vectorize
不起作用,因为解包没有以正确的方式完成。即使我重写f
,使其具有形状数组(3,3),我该如何告诉numpy在第一个轴上迭代并获取3x3子阵列?没有自动的方法可以做到这一点,您需要编写f
,使其与点阵列而不是单个点一起工作。我认为这几乎是可以的,尽管您需要更改第一个if
,但在>代码> No.Limal.MultUng/Mult>调用和可能的一些东西(<代码> SotTyTrime3/代码>,我假设它是另一个如果你的函数也需要修改的话。BTW,考虑替换每个<代码> PoW(x,2)< /Cube >调用<代码> NP.x(平方)(x)< /Cord>。HijJeHESA你到底指的是什么意思?“您需要以一种方式来编写f,使其与点数组而不是单点一起工作。”通过p
将a、b、c
替换为参数,其中p
是一个形状数组(3,3),然后解包p
似乎不起作用。你的意思是f
的输入参数的形状必须与A
的形状相同,至少有三个维度?感谢np.square(x)
@patrik的提示否,我的意思是函数必须设计为采用三个形状为(2133,3)(或(X,3)并直接返回(2133,3)结果。例如,您需要将ex=(b-a)/(np.linalg.norm(b-a))
更改为ex=(b-a)/(np.linalg.norm(b-a,axis=0))
,等等。每个语句必须同时处理所有点。没有通用的自动化方法(也就是说,如果性能不是一个大问题,那么为了方便起见,可以使用循环或理解)。谢谢@hpaulj。f确实可能产生一个“无”。f计算三个点的三边测量点,有时对于给定的r1
,它根本不存在。性能是什么
def sort_triple(a, b, c):
pts = np.stack((a, b, c), axis=1)
xSorted = pts[np.arange(pts.shape[0])[:, None], np.argsort(pts[:, :, 0])]
orientation = np.cross(xSorted[:, 1] - xSorted[:, 0], xSorted[:, 2] -
xSorted[:, 0])[:, 2] >= 0
xSorted_flipped = np.stack((xSorted[:, 0], xSorted[:, 2], xSorted[:, 1]),
axis=1)
xSorted = np.where(orientation[:, np.newaxis, np.newaxis], xSorted,
xSorted_flipped)
return map(np.squeeze, np.split(xSorted, 3, axis=1))
def f(A, r1, r2=None, r3=None):
a, b, c = map(np.squeeze, np.split(A, 3, axis=1))
a, b, c = sort_triple(a, b, c)
if any(r is None for r in (r2, r3)):
r2, r3 = (r1, r1)
ex = (b - a) / (np.linalg.norm(b - a, axis=1))[:, np.newaxis]
i = inner1d(ex, (c - a))
ey = ((c - a - i[:, np.newaxis]*ex) /
(np.linalg.norm(c - a - i[:, np.newaxis]*ex, axis=1))[:, np.newaxis])
ez = np.cross(ex, ey)
d = np.linalg.norm(b - a, axis=1)
j = inner1d(ey, c - a)
x = (np.square(r1) - np.square(r2) + np.square(d)) / (2 * d)
y = ((np.square(r1) - np.square(r3) + np.square(i) + np.square(j)) / (2*j) -
i/j*x)
z_square = np.square(r1) - np.square(x) - np.square(y)
mask = z_square < 0
z_square[mask] *= 0
z = np.sqrt(z_square)
z[mask] = np.nan
intersection = (a + x[:, np.newaxis] * ex + y[:, np.newaxis] * ey +
z[:, np.newaxis] * ez)
return intersection