Julia 如何使用linspace上的理解创建矩阵

Julia 如何使用linspace上的理解创建矩阵,julia,Julia,我想生成一个nx3矩阵,其中n是像素数(宽度*高度) 但是,当我运行此命令时,我得到一个: 16-element Array{Array{Float64,2},1} 而不是我想要的16x3数组{Float64,2}。我显然没有正确地使用理解来构造矩阵。我尝试使用理解来创建元组数组,但我无法将这些元组转换为矩阵。这里的问题是数组理解将为我们提供嵌套数组,而不是矩阵。这是正确的理解行为,它不会为我们做额外的猜测,因此我们需要手动将嵌套数组转换为矩阵,这可以使用带有splating运算符(…)的vc

我想生成一个nx3矩阵,其中n是像素数(宽度*高度)

但是,当我运行此命令时,我得到一个:

16-element Array{Array{Float64,2},1}

而不是我想要的16x3
数组{Float64,2}
。我显然没有正确地使用理解来构造矩阵。我尝试使用理解来创建元组数组,但我无法将这些元组转换为矩阵。

这里的问题是
数组理解将为我们提供嵌套数组,而不是
矩阵。这是正确的理解行为,它不会为我们做额外的猜测,因此我们需要手动将嵌套数组转换为矩阵,这可以使用带有splating运算符(
)的
vcat
来完成:

看起来你是从二维欧几里德空间构造的。使用
Base.Iterators.product
是创建迭代器的一种更简洁、更健壮的方法:

julia> w = linspace(-1,1,3)
-1.0:1.0:1.0

julia> h = linspace(-1,1,2)
-1.0:2.0:1.0

julia> r = 1.0
1.0

julia> viewDirections = [collect(i) for i in Iterators.product(w, h, r)]
3×2 Array{Array{Float64,1},2}:
 [-1.0, -1.0, 1.0]  [-1.0, 1.0, 1.0]
 [0.0, -1.0, 1.0]   [0.0, 1.0, 1.0] 
 [1.0, -1.0, 1.0]   [1.0, 1.0, 1.0] 

julia> hcat(viewDirections...).'
6×3 Array{Float64,2}:
 -1.0  -1.0  1.0
  0.0  -1.0  1.0
  1.0  -1.0  1.0
 -1.0   1.0  1.0
  0.0   1.0  1.0
  1.0   1.0  1.0
请注意,坐标顺序与原始版本不同,这是因为Julia是列主迭代器,
迭代器。product
将迭代最右边的维度“最外层”,即
[[i j r]对于j in y对于i in x]
。如果顺序在您的用例中很重要,请注意它。 以下是
width/height
变大时的一些基准测试结果:

julia> w = linspace(-1,1,300)
-1.0:0.006688963210702341:1.0

julia> h = linspace(-1,1,200)
-1.0:0.010050251256281407:1.0

julia> foo(w,h,r) = hcat([collect(i) for i in Iterators.product(w, h, r)]...).'

julia> bar(w,h,r) = vcat([[i j r] for i in w for j in h]...)

julia> @btime foo($w,$h,$r);
  6.172 ms (60018 allocations: 10.99 MiB)

julia> @btime bar($w,$h,$r);
  11.294 ms (360028 allocations: 17.02 MiB)

我认为这可能是一个解决方案,重新解释(Float64,viewDirections,(3,nPixels))非常好!这种splat和vcat技术工作得非常好。是的,为光线跟踪器创建标准化的摄影机空间坐标。@RobertF.Dickerson如果您不关心矩阵中的坐标顺序,那么
hcat+product
是更好的选择(大约快2倍)。仅供参考,如果您可以在迭代器中将计算写成i的
。product(w,h,r)不要(i)结束
。Matlab和其他速度较慢的语言要求您计算这样的数组,因为需要矢量化以获得良好的性能,但对于Julia来说,这不是一个问题。@tholy矩阵不是创建了两次吗?(转置)@Liso在那里创建了许多小矩阵/向量(注意tholy的意思是最终结果),因此转置不是什么大问题;)另外,是否使用转置取决于您编写以下代码的方式,我使用转置是因为OP的要求是16x3矩阵。如上所述,在某些用例中,使用for循环可以完全避免所有这些问题。
julia> w = linspace(-1,1,3)
-1.0:1.0:1.0

julia> h = linspace(-1,1,2)
-1.0:2.0:1.0

julia> r = 1.0
1.0

julia> viewDirections = [collect(i) for i in Iterators.product(w, h, r)]
3×2 Array{Array{Float64,1},2}:
 [-1.0, -1.0, 1.0]  [-1.0, 1.0, 1.0]
 [0.0, -1.0, 1.0]   [0.0, 1.0, 1.0] 
 [1.0, -1.0, 1.0]   [1.0, 1.0, 1.0] 

julia> hcat(viewDirections...).'
6×3 Array{Float64,2}:
 -1.0  -1.0  1.0
  0.0  -1.0  1.0
  1.0  -1.0  1.0
 -1.0   1.0  1.0
  0.0   1.0  1.0
  1.0   1.0  1.0
julia> w = linspace(-1,1,300)
-1.0:0.006688963210702341:1.0

julia> h = linspace(-1,1,200)
-1.0:0.010050251256281407:1.0

julia> foo(w,h,r) = hcat([collect(i) for i in Iterators.product(w, h, r)]...).'

julia> bar(w,h,r) = vcat([[i j r] for i in w for j in h]...)

julia> @btime foo($w,$h,$r);
  6.172 ms (60018 allocations: 10.99 MiB)

julia> @btime bar($w,$h,$r);
  11.294 ms (360028 allocations: 17.02 MiB)