我需要沿着定义的线(3D)以相等的间距计算n个点(3D)。 我知道线的起点和终点。首先,我用了
for k in range(nbin):
step = k/float(nbin-1)
bin_point.append(beam_entry+(step*(beamlet_intersection-beam_entry)))
然后,我发现使用append for large arrays需要更多时间,然后我改变了代码:
bin_point = [start_point+((k/float(nbin-1))*(end_point-start_point)) for k in range(nbin)]
我得到一个建议,使用newaxis将进一步缩短时间。 修改后的代码看起来像这样。
step = arange(nbin) / float(nbin-1)
bin_point = start_point + ( step[:,newaxis,newaxis]*((end_pint - start_point))[newaxis,:,:] )
但是,我无法理解newaxis函数,我也怀疑,如果start_point和end_point的结构或形状发生了变化,相同的代码是否会起作用。同样,我如何使用newaxis mdoify以下代码
for j in range(32): # for all los
line_dist[j] = sqrt([sum(l) for l in (end_point[j]-start_point[j])**2])
很抱歉这么笨重,更清楚start_point和end_point的结构是
array([ [[1,1,1],[],[],[]....[]],
[[],[],[],[]....[]],
[[],[],[],[]....[]]......,
[[],[],[],[]....[]] ])
答案 0 :(得分:2)
问题中对newaxis版本的解释:这些是不矩阵乘法,ndarray乘法是逐个元素乘以broadcasting。 step [:,newaxis,newaxis]为num_steps x 1 x 1,point [newaxis,:,:]为1 x num_points x num_dimensions。将形状(num_steps x 1 x 1)和(1 x num_points x num_dimensions)的ndarray一起广播将起作用,因为广播规则是每个维度应该是1或相同;它只是意味着“使用维度1重复数组的次数与其他数组的相应维度一样多”。这导致具有形状的ndarray(num_steps x num_points x num_dimensions)以非常有效的方式; i,j,k下标将是沿第j行的第i步的第k个坐标(由第j对起点和终点给出)。
操作实例:
>>> start_points = numpy.array([[1, 0, 0], [0, 1, 0]])
>>> end_points = numpy.array([[10, 0, 0], [0, 10, 0]])
>>> steps = numpy.arange(10)/9.0
>>> start_points.shape
(2, 3)
>>> steps.shape
(10,)
>>> steps[:,numpy.newaxis,numpy.newaxis].shape
(10, 1, 1)
>>> (steps[:,numpy.newaxis,numpy.newaxis] * start_points).shape
(10, 2, 3)
>>> (steps[:,numpy.newaxis,numpy.newaxis] * (end_points - start_points)) + start_points
array([[[ 1., 0., 0.],
[ 0., 1., 0.]],
[[ 2., 0., 0.],
[ 0., 2., 0.]],
[[ 3., 0., 0.],
[ 0., 3., 0.]],
[[ 4., 0., 0.],
[ 0., 4., 0.]],
[[ 5., 0., 0.],
[ 0., 5., 0.]],
[[ 6., 0., 0.],
[ 0., 6., 0.]],
[[ 7., 0., 0.],
[ 0., 7., 0.]],
[[ 8., 0., 0.],
[ 0., 8., 0.]],
[[ 9., 0., 0.],
[ 0., 9., 0.]],
[[ 10., 0., 0.],
[ 0., 10., 0.]]])
如您所见,这会产生正确答案:)在这种情况下,广播(10,1,1)和(2,3)会产生(10,2,3)。你所拥有的是广播(10,1,1)和(1,2,3),这是完全相同的,也产生(10,2,3)。
问题的距离部分的代码不需要newaxis:输入是num_points x num_dimensions,输出是num_points,因此必须删除一个维度。这实际上是你总结的轴。这应该有效:
line_dist = numpy.sqrt( numpy.sum( (end_point - start_point) ** 2, axis=1 )
这里numpy.sum(...,axis = 1)表示仅沿该轴的总和,而不是所有元素:形状为num_points的ndarray x沿轴= 1总和的num_dimensions产生带有num_points的结果,这是正确的。
编辑:删除没有广播的代码示例。 编辑:修正了索引的顺序。 编辑:添加了line_dist
答案 1 :(得分:1)
我不是通过理解你写的所有内容,而是我已经可以告诉你的一些事情;也许他们会帮忙。
newaxis
是一个标记,而不是一个函数(事实上,它是普通的None
)。它用于将(未使用的)维度添加到多维值。有了它,您可以使用2D值(甚至更多)制作3D值。输入值中已存在的每个维度必须由索引中的冒号:
表示(假设您要使用所有值,否则它将超出我们的用例),要添加的维度由{{表示1}}。
例:
输入是一维向量(1D):1,2,3
输出应为矩阵(2D)
有两种方法可以实现这一目标;向量可以用每个值填充一行,或者向量可以只填充矩阵的第一行和唯一行。第一个由newaxis
创建,第二个由vector[:,newaxis]
创建。结果:
vector[newaxis,:]
(当然,多维值的维度由数组的嵌套表示。)
如果输入中有更多维度,请多次使用冒号(否则将忽略更深的嵌套维度,即将数组视为简单值)。我不会粘贴这里的表示,因为当使用嵌套括号在2D显示器上写入3D和4D值时,由于光学复杂性,它不会澄清事物。无论如何,我希望它变得清晰。
答案 2 :(得分:0)
newaxis以这样的方式重新整形数组,这样当你多次使用numpy时就会使用广播。 Here is a good tutorial on broadcasting
step[:, newaxis, newaxis]
与step.reshape((step.shape[0], 1, 1))
相同(如果step
为1d)。重塑的任何一种方法都应该非常快,因为在numpy中重新整形数组非常简单,它只是查看数组,特别是因为你应该只进行一次。