# Way to make contour plot from 3 vectors?

**URL:** <https://discourse.julialang.org/t/way-to-make-contour-plot-from-3-vectors/20118>\
**Category:** General Usage\
**Tags:** question\
**Created:** [January 26, 2019, 5:53am UTC](https://discourse.julialang.org/t/way-to-make-contour-plot-from-3-vectors/20118 "2019-01-26T05:53:44Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [January 26, 2019, 5:53am UTC](https://discourse.julialang.org/t/way-to-make-contour-plot-from-3-vectors/20118/1 "2019-01-26T05:53:44Z")

</div>

Just ran into this problem with Julia. It is a repeat of these questions though:

- [Matlab:Make a contour plot with 3 vectors](https://stackoverflow.com/questions/12614686/matlabmake-a-contour-plot-with-3-vectors)
- [Create a contour plot from 3 vectors](https://stackoverflow.com/questions/43030227/create-a-contour-plot-from-3-vectors)
- [Contour plot with 3 vector](https://stackoverflow.com/questions/19560229/contour-plot-with-3-vector)
- [Constructing a Contour Plot with Three Different Arrays Corresponding to X, Y, and Z in Python](https://stackoverflow.com/questions/41093140/constructing-a-contour-plot-with-three-different-arrays-corresponding-to-x-y-a)

* * *

Summarized, you have:

- two vectors that hold points on an irregularly spaced grid: `(x,y)`
- one vector with function values at each of those points: `z = f(x,y)`

How do you plot a heatmap of this?

// using Plots.jl (and maybe some Interpolation package)

---

<div class="post-metadata">

**Author:** ![Mattriks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattriks/32/351_2.png) [@Mattriks](https://discourse.julialang.org/u/Mattriks)\
**Post date:** [January 26, 2019, 7:34am UTC](https://discourse.julialang.org/t/way-to-make-contour-plot-from-3-vectors/20118/2 "2019-01-26T07:34:27Z")

</div>

Here’s a Gadfly example:  
[https://github.com/GiovineItalia/Gadfly.jl/pull/1150#issue-190151930](https://github.com/GiovineItalia/Gadfly.jl/pull/1150#issue-190151930)  
The function `rsm` there could be used to give you a regular grid for any plotting package. Note it was written for Julia 0.6 or earlier, so would need updating for Julia 0.7/1.x.

---

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [January 26, 2019, 6:49pm UTC](https://discourse.julialang.org/t/way-to-make-contour-plot-from-3-vectors/20118/3 "2019-01-26T18:49:44Z")

</div>

What would need updating besides linspaces? This seems like a relatively common modeling problem

---

<div class="post-metadata">

**Author:** ![Mattriks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattriks/32/351_2.png) [@Mattriks](https://discourse.julialang.org/u/Mattriks)\
**Post date:** [January 27, 2019, 1:32am UTC](https://discourse.julialang.org/t/way-to-make-contour-plot-from-3-vectors/20118/4 "2019-01-27T01:32:21Z")

</div>

Here is a Julia 1.x update for a response surface model:

```julia
import Cairo
using DataFrames, Gadfly, RDatasets

module t
using DataFrames, Statistics

VecOrSA = Union{Vector, SubArray}
expand_grid(xv::AbstractRange, yv::AbstractRange) = 
    vcat([[x y] for x in xv, y in yv]...)

function rsm(xv::VecOrSA, yv::VecOrSA, zv::VecOrSA, k::Int; 
        xlim::Tuple=extrema(xv), ylim::Tuple=extrema(yv))
    # k is the order of the polynomial surface
    y = Vector{Float64}(zv)
    μx, μy = mean(xv), mean(yv)
    p = reshape([1:k;],1,:)
    X = hcat(ones(length(xv)), (xv.-μx).^p, (yv.-μy).^p)    
    B = X'X \ X'y
    xp = range(xlim[1], xlim[2], length=11)
    yp = range(ylim[1], ylim[2], length=11)
    g = expand_grid(xp, yp)
    X = hcat(ones(size(g,1)), (g[:,1].-μx).^p, (g[:,2].-μy).^p)
    return DataFrame(x=g[:,1], y=g[:,2], z=X*B)
end

end

Doz = dropmissing(dataset("datasets","airquality"), disallowmissing=true)
Doz[:SolarRad] = Doz[:,2] .> 200
labelD = Dict(false=>"SolarRad ≤200", true=>"SolarRad >200")

Dpredict = by(Doz, :SolarRad, [:Wind, :Temp, :Ozone] =>
    x->t.rsm(x.Wind, x.Temp, x.Ozone, 2, xlim=(0, 21), ylim=(50,100)) )

set_default_plot_size(16cm, 8cm)
p = plot(Doz, x=:Wind, y=:Temp, xgroup=:SolarRad, color=:Ozone, 
    Geom.subplot_grid(
        layer( Geom.point),
        layer(Dpredict, x=:x, y=:y, z=:z, xgroup=:SolarRad, Geom.contour),
        Guide.xticks(ticks=[0:5:20;]) ),
    Scale.color_continuous(minvalue=0, maxvalue=200),
    Scale.xgroup(labels=x->labelD[x], levels=[false, true])
    )

```

![rsm](https://global.discourse-cdn.com/julialang/original/3X/1/b/1bc76ad63728a683296445b23496b2dedbe29d1e.png)
