Analog of markevery in Plots.jl?

Matplotlib had a nice feature, markevery=n, that, for a bivariate data set, allowed you to only plot every n-th point. This was quite useful if you had an abundance of data and wanted to reduce the graphical intensity of a figure. Is there any natural analog in Plots.jl? Could there be?

1 Like

you should be able to use view(x, 1:n:length(x))!

1 Like

I’d say that is preferable to adding a keyword to plot

That works if you are just plotting a vector.

But if you are using a recipe that generates the plots for you, and you are plotting some complicated struct, it might be difficult create such a view perhaps?

I guess that is true. I can’t really think of a concrete example but that’s not to say it won’t occur in the wild.

Let’s say you are plotting some struct that represents a bunch of solutions to some ODE with a recipe. Maybe you have a ton of timesteps but for the plot you don’t want the plots to be so dense.

Here, you just want to tell Plots.jl, please spread the points out a bit, without having to mess with the struct itself.

2 Likes

So that would be part of the recipe then, right? My point is, I think the most basic plotting construct should just accept views and not do this via kw_args - however, how you downsample in recipes will be much more domain specific and possibly will need kw_args :wink:

1 Like

I think so too. It would be easy to implement a thin kwarg in a recipe. You’d lose the applicability across Plots but have complete flexibility in terms of how to interpret it in the context of your recipe.

A disadvantage of the view approach is that it’d apply to the line and the symbol. In matplotlib, markevery shows the line in full resolution. Using view, you have to plot!each series twice, once for the line and once for the symbols, and that makes it harder to make nice legends.

Thanks for explaining the marker-line dichotomy, that makes the mechanism make more sense. Oh and primary = false is your friend wrt the legend.

Hi all, sorry for restarting this old thread. I had the same issue and worked out a solution in case people are reading this. Actually, for my sake, markevery wouldn’t have been exactly what I was after since it doesn’t account for changes in y.

using Plots, StatsFuns
pyplot()

function fixmarkerspacing(x, y, maxspace, rangex, rangey)
   newx = [x[1]]
   newy = [y[1]]
   sumnorm = 0
   for i ∈ 2:length(x)
      sumnorm += sqrt(((x[i] - x[i-1])/rangex)^2 + ((y[i] - y[i-1])/rangey)^2)
      if sumnorm > maxspace
         push!(newx,x[i])
         push!(newy,y[i])
         sumnorm = sumnorm - maxspace
         if sumnorm > maxspace # In case a jump in y was very large
            sumnorm = 0
         end
      end
   end
   return newx, newy
end

x = -10:0.05:10
y = logistic.(x)
newx, newy = fixmarkerspacing(x, y, 0.2, 20, 1)
plot([], [], markershape = :square, label = "foo", linecolor = :blue, markercolor = :red)
plot!(x, y, linecolor = :blue, label = "")
plot!(newx, newy, line = false, markershape = :square, label = "", markercolor = :red)

With the result:
evenmarkers