Hi all,
I have this code:
using Plots, LaTeXStrings
gr()
f(x)=floor(x)
plot(f,0,10,ylim=(-12,12))
Since [ x ] denotes the gretest integer less than or equal to x, I want to plot it like this:
Anyone know how?
Hi all,
I have this code:
using Plots, LaTeXStrings
gr()
f(x)=floor(x)
plot(f,0,10,ylim=(-12,12))
Since [ x ] denotes the gretest integer less than or equal to x, I want to plot it like this:
Anyone know how?
One way:
using Plots; gr()
xp = [[i, i+1 - 5*eps()] for i in -12:11]
p = plot(ylim=(-12,12), framestyle = :origin)
for x in xp
plot!(x, floor.(x), c=:black)
scatter!(x, floor.(x), ms=3, msc=:black, mc=[:black, :white])
end
p
NB: it would be faster not to loop and plot everything in one go. It would require inserting NaNs at the breaks.
Creating step functions is not as simple as just using floor().
I tried to reproduce the original plot (not the best code, but it has been fun):
f(x) = floor(x)
x = -5:1:4
y = f.(x)
plot(x[1:2], [y[1], y[1]], label=L"f(x) = \lfloor x \rfloor", legend=:bottomleft,legend_foreground_color=:white, legend_font_color=:blue, color=:blue, showaxis=false, tickfontcolor=:white)
# axis and
hline!((0,0), color=:black, label="")
vline!((0,0), color=:black, label="")
for i in x
if i!= 0
annotate!(i,-0.2, (i, 7))
end
end
for i in y
if i != 0
annotate!(-.2, i, (i, 7))
end
end
annotate!(-.2, -.2, ("0", 7))
for i in 2:length(x)-1
plot!(x[i:i+1], [y[i], y[i]], label="", color=:blue, lw=2)
scatter!(x[i], y[i], marker=:circle, markersize=8, label="")
end
scatter!(x[1:end-1], y[1:end-1], markersize=3, markercolor=:blue, label="")
scatter!(x[2:end], y[1:end-1], markersize=3, markercolor=:white, label="")
Here is a version without the plot loop using NaN
at the breaks:
using Plots; gr()
x = -12:12
xp = [[i, i+1 - 5*eps(), NaN] for i in x[1:end-1]]
xx = collect(Iterators.flatten(xp))
yy = floor.(xx)
plot(xx, yy, c=:black, label=false, framestyle = :origin)
scatter!(xx', yy', msc=:black, mc=[:black :white :white], ms=3)
It is really beautiful,
I want to ask
plot(x[1:2], [y[1], y[1]]
why there are two y[1] ? I want to know the details behind it.
Note that if you want the axes centered at the origin, you should use plot argument: framestyle = :origin
. NB: updated in examples above
Thanks for the explanation.
Because the first step goes from point (x[1], y[1])
to (x[2], y[1])
. It’s the same for the rest of the steps inside the for loop.
I have cleaned my version a little bit (thanks to @rafael.guerra):
# Plot configuration
plot(legend_title=L"f(x) = \lfloor x \rfloor", legend=:bottomleft,legend_foreground_color=:white, legend_title_font_color=:blue, color=:blue, framestyle=:origin, ticks=x)
# Steps drawing
for i in 1:length(x)-1
plot!(x[i:i+1], [y[i], y[i]], label="", color=:blue, lw=2)
end
# Points at the beginning ot the steps
scatter!(x[1:end-1], y[1:end-1], markersize=3, markercolor=:blue, label="")
# End points
scatter!(x[2:end], y[1:end-1], markersize=3, markercolor=:white, label="")
# Adds '0' close to origin
annotate!(-.22, -.26, ("0", 8))
I’m sure it could be improved, but I think it’s quite close to the original.
Tried this in Jupyter Notebook and compare with your old code.
It is simpler, so we can remove the old
f(x) = floor(x)
x = -5:1:4
y = f.(x)
plot(x[1:2], [y[1], y[1]], label=L"f(x) = \lfloor x \rfloor", legend=:topleft,legend_foreground_color=:white, legend_font_color=:blue3, color=:blue3, showaxis=false, tickfontcolor=:white)
# axis and
hline!((0,0), color=:black, label="")
vline!((0,0), color=:black, label="")
for i in x
if i!= 0
annotate!(i,-0.2, (i, 7))
end
end
for i in y
if i != 0
annotate!(-.2, i, (i, 7))
end
end
for i in 2:length(x)-1
plot!(x[i:i+1], [y[i], y[i]], label="", color=:blue3, lw=2)
scatter!(x[i], y[i], marker=:circle, markersize=8, label="")
end