在Julia中使用ndgrid / meshgrid功能

时间:2017-06-16 04:50:19

标签: julia

我试图在Julia中找到与MATLAB meshgridndgrid相似的功能。我知道Julia在the examples中定义了ndgrid,但是当我尝试使用它时,我收到以下错误。

  

UndefVarError:未定义ndgrid

任何人都知道如何使内置ndgrid函数工作,或者可能找到另一个我找不到的函数或提供这些方法的库(内置函数会更受欢迎)?在这种情况下,我宁愿不写自己的。

谢谢!

3 个答案:

答案 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 ndgridhttps://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]]...,)