我试图在Julia中找到与MATLAB meshgrid
或ndgrid
相似的功能。我知道Julia在the examples中定义了ndgrid
,但是当我尝试使用它时,我收到以下错误。
UndefVarError:未定义ndgrid
任何人都知道如何使内置ndgrid
函数工作,或者可能找到另一个我找不到的函数或提供这些方法的库(内置函数会更受欢迎)?在这种情况下,我宁愿不写自己的。
谢谢!
答案 0 :(得分:9)
我们更愿意避免使用这些功能,因为它们会分配通常不必要的数组。这些数组中的值具有这样的规则结构,它们不需要存储;它们可以在迭代期间计算。例如,一种替代方法是编写数组理解:
julia> [ 10i + j for i=1:5, j=1:5 ]
5×5 Array{Int64,2}:
11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
41 42 43 44 45
51 52 53 54 55
或者,您可以编写for
循环,或迭代product
迭代器:
julia> collect(Iterators.product(1:2, 3:4))
2×2 Array{Tuple{Int64,Int64},2}:
(1, 3) (1, 4)
(2, 3) (2, 4)
答案 1 :(得分:1)
我确实发现有时在numpy中使用诸如meshgrid
之类的函数很方便。列表理解很容易做到:
function meshgrid(x, y)
X = [i for i in x, j in 1:length(y)]
Y = [j for i in 1:length(x), j in y]
return X, Y
end
例如
x = 1:4
y = 1:3
X, Y = meshgrid(x, y)
现在
julia> X
4×3 Array{Int64,2}:
1 1 1
2 2 2
3 3 3
4 4 4
julia> Y
4×3 Array{Int64,2}:
1 2 3
1 2 3
1 2 3
1 2 3
但是,我没有发现这会使代码运行比使用迭代更快。这就是我的意思:
定义后
x = 1:1000
y = x
X, Y = meshgrid(x, y)
我对以下两个功能做了基准测试
using Statistics
function fun1()
return mean(sqrt.(X.*X + Y.*Y))
end
function fun2()
sum = 0.0
for i in 1:1000
for j in 1:1000
sum += sqrt(i*i + j*j)
end
end
return sum / (1000*1000)
end
以下是基准测试结果:
julia> @btime fun1()
8.310 ms (19 allocations: 30.52 MiB)
julia> @btime run2()
1.671 ms (0 allocations: 0 bytes)
meshgrid
方法既很慢,又占用更多内存。任何Julia专家都知道为什么吗?我知道Julia是一种不同于Python的编译语言,因此迭代不会比矢量化慢,但是我不明白为什么vector(array)计算比迭代慢很多倍。 (对于较大的N,此差异甚至更大。)
编辑:阅读this post之后,我获得了“ meshgrid”方法的以下更新版本。这个想法不是预先创建一个网格网格,而是通过茱莉亚强大的元素级数组操作在计算中进行:
x = collect(1:1000)
y = x'
function fun1v2()
mean(sqrt.(x .* x .+ y .* y))
end
这里的窍门是在大小为M的列数组和大小为N的行数组之间返回{by by N by N}的.+
。它为您做“网格”。此功能比fun1
快3倍,尽管速度不如fun2
。
julia> @btime fun1v2()
3.189 ms (24 allocations: 7.63 MiB)
765.8435104896155
答案 2 :(得分:1)
在上面,@ChrisRackauckas 建议使用懒惰的运算符来执行此操作的“正确方法”,但他没有解决。
现在有一个注册包,里面有lazy ndgrid
:
https://github.com/JuliaArrays/LazyGrids.jl
比里面的版本更通用
VectorizedRoutines.jl
因为它可以处理不同类型的向量,例如,
ndgrid(1:3, Float16[0:2], ["x", "y", "z"])
。
文档中有 Literate.jl
个示例表明惰性性能非常好。
当然懒惰meshgrid
只是一步之遥:
meshgrid(y,x) = (ndgrid_lazy(x,y)[[2,1]]...,)