# Modifying Plots.jl subplots in-place

**URL:** <https://discourse.julialang.org/t/modifying-plots-jl-subplots-in-place/106069>\
**Category:** General Usage\
**Tags:** question, plotting, animations, subplots\
**Created:** [November 11, 2023, 9:48am UTC](https://discourse.julialang.org/t/modifying-plots-jl-subplots-in-place/106069 "2023-11-11T09:48:18Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![CM1](https://avatars.discourse-cdn.com/v4/letter/c/41988e/32.png) [@CM1](https://discourse.julialang.org/u/CM1)\
**Post date:** [November 11, 2023, 9:48am UTC](https://discourse.julialang.org/t/modifying-plots-jl-subplots-in-place/106069/1 "2023-11-11T09:48:18Z")

</div>

As discussed recently in [this thread](https://discourse.julialang.org/t/how-to-create-an-animation-based-on-t-x-y-and-z-data/25672/8), we are wondering whether it is possible to create one initial plot with subplots, which then can be individually modified by `push!`.

So instead of creating two separate plots and then combining them in a call to `plot`:

```julia
using Plots

N = 200

u1 = 20*rand(3, N)
u2 = 15*rand(3, N)

plt1 = plot3d(
    1,
    xlim = (-30, 30),
    ylim = (-30, 30),
    zlim = (0, 60),
    title = ["Some trajectory"],
    legend = false,
    marker = 2,
)

plt2 = plot3d(
    1,
    xlim = (-30, 30),
    ylim = (-30, 30),
    zlim = (0, 60),
    title = ["Other trajectory"],
    legend = false,
    marker = 2,
)

@gif for i in range(1, size(u1, 2))
    push!(plt1, u1[:, i]...)
    push!(plt2, u2[:, i]...)
    plot(plt1, plt2)
end every 10

```

I’d expect something like

```julia
N = 200

u1 = 20*rand(3, N)
u2 = 15*rand(3, N)

plt = plot3d(
    1,
    xlim = (-30, 30),
    ylim = (-30, 30),
    zlim = (0, 60),
    title = ["Some trajectory" "Other trajectory"],
    legend = false,
    marker = 2,
    layout = (1, 2)
)

@gif for i in range(1, size(u1, 2))
    push!(plt[1], u1[:, i]...)
    push!(plt[2], u2[:, i]...)
end every 10

```

or even being able to push to both subplots in one joint call.

---

<div class="post-metadata">

**Author:** ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)\
**Post date:** [November 11, 2023, 12:01pm UTC](https://discourse.julialang.org/t/modifying-plots-jl-subplots-in-place/106069/2 "2023-11-11T12:01:02Z")

</div>

Is this animation what you are expecting?

```julia
using Plots
n=150
t =range(0, 4pi, n)
x=sin.(t)
y=t
z=cos.(t)
l = @layout [a b] 
p = plot(layout = l, xlim = (-1.2, 1.2), ylim = (-0.2, 4pi+0.2),
        zlim = (-1.2, 1.2), legend = false);

@gif for i in 1:5:n
    plot!(p[1], x[1:i], y[1:i], z[1:i])
    plot!(p[2], x[1:i], y[1:i], z[1:i])
end every 3

```

I changed your data because it wasn’t quite visible how it works.

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [November 11, 2023, 2:28pm UTC](https://discourse.julialang.org/t/modifying-plots-jl-subplots-in-place/106069/3 "2023-11-11T14:28:35Z")

</div>

I think this is how it’s supposed to look like in the end (the data in the original post just plots random points in succession to show the idea).

What isn’t quite clear to me is whether updating the plot using `push!` (as described in this example of the docs: [Home · Plots](https://docs.juliaplots.org/latest/#simple-is-beautiful) ) or using `plot!` (as you showed) should be preferred when animating a plot. Is one faster than the other?

And at least in the example from the original post, using the `push!` method with subplots doesn’t seem to work. Perhaps we were doing it wrong…

---

<div class="post-metadata">

**Author:** ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)\
**Post date:** [November 11, 2023, 2:40pm UTC](https://discourse.julialang.org/t/modifying-plots-jl-subplots-in-place/106069/4 "2023-11-11T14:40:49Z")

</div>

It doesn’t work with `push!`. Just replace `plot!` by `push!`, and see the error message, which tells, as I remember ( I’m writing from my phone) `you cannot push to subplots`.

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [November 11, 2023, 2:50pm UTC](https://discourse.julialang.org/t/modifying-plots-jl-subplots-in-place/106069/5 "2023-11-11T14:50:36Z")

</div>

> [@empet](#):
>
> It doesn’t work with `push!`.

That’s what I said 😅  
The error I get is just a generic `MethodError`, hence the question if this is just a “missing feature” or if there is more behind it.

> **Stacktrace**
>
> ```julia-auto
> julia> @gif for i in 1:5:n
> push!(p[1], x[1:i], y[1:i], z[1:i])
> push!(p[2], x[1:i], y[1:i], z[1:i])
> end every 3
> ERROR: MethodError: no method matching push!(::Plots.Subplot{Plots.GRBackend}, ::Vector{Float64})
> 
> Closest candidates are:
> push!(::Any, ::Any, ::Any)
> @ Base abstractarray.jl:3389
> push!(::Any, ::Any, ::Any, ::Any...)
> @ Base abstractarray.jl:3390
> push!(::DataStructures.DefaultDict, ::Any)
> @ DataStructures ~/.julia/packages/DataStructures/MKv4P/src/default_dict.jl:139
> ...
> 
> Stacktrace:
> [1] push!(A::Plots.Subplot{Plots.GRBackend}, a::Vector{Float64}, b::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64})
> @ Base ./abstractarray.jl:3389
> [2] push!(A::Plots.Subplot{Plots.GRBackend}, a::Vector{Float64}, b::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, c::Vector{Float64})
> @ Base ./abstractarray.jl:3390
> [3] macro expansion
> @ ./REPL[52]:2 [inlined]
> [4] top-level scope
> @ ~/.julia/packages/Plots/sxUvK/src/animation.jl:251
> 
> ```

I couldn’t find out if there is a technical reason why `push!`ing new data to subplots doesn’t work, but `push!`ing to a regular plot works. From your answer I understand that there might be one. Do you know if this is documented somewhere?

> [@Sevi](#):
>
> (as described in this example of the docs: [Home · Plots](https://docs.juliaplots.org/latest/#simple-is-beautiful) )

The example right below the Lorenz attractor also uses subplots, but creates a new plot every iteration. Seems like this (or the approach by @empet ) is the only supported way at the moment?

---

<div class="post-metadata">

**Author:** ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)\
**Post date:** [November 11, 2023, 4:03pm UTC](https://discourse.julialang.org/t/modifying-plots-jl-subplots-in-place/106069/6 "2023-11-11T16:03:59Z")

</div>

When the two subplots have distinct axes limits, then the above code is slightly modified, as follows:

```julia
using Plots
n=150
t =range(0, 4pi, n)
x=sin.(t)
y=t
z=cos.(t)
l = @layout [a b] 
p = plot(layout = l)
@gif for i in 1:5:n
  plot!(p[1], x[1:i], y[1:i], z[1:i], xlim = (-1.2, 1.2), ylim = (-0.2, 4pi+0.2),
        zlim = (-1.2, 1.2), legend = false)
  plot!(p[2], z[1:i], x[1:i], y[1:i], xlim = (-1.2, 1.2), ylim = (-1.2, 1.2),
        zlim=(-0.2, 4pi+0.2), legend=false)
end every 3

```
