# How to Plot Step Functions [x] Correctly in Julia?

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.

3 Likes

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, y], 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="")
``````

1 Like

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,

``````plot(x[1:2], [y, y]
``````

why there are two y ? 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, y)` to `(x, y)`. 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.

2 Likes

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, y], 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

``````

Hi @runjaj

I am trying to plot `[x + 1/2]` do you know what to edit in your code? Thanks

Hi!

One simple option is just changing the function to:

``````f(x) = floor(x + 1/2)
``````

And the step of the `x` to `0.5`:

``````x = -5:.5:4
``````

In this case, you’ll get: Is this what you want?

If you want to avoid plotting the central point of each step, the easiest way is set `x` to:

``````x = -5.5:1:4.5
`````` This is the code I used:

``````f(x) = floor(x + 1/2)
x = -5.5:1:4.5
y = f.(x)

plot(x[1:2], [y, y], label=L"f(x) = \lfloor x + 1/2 \rfloor", legend=:bottomleft,legend_foreground_color=:white,
legend_font_color=:blue, color=:blue, showaxis=false, tickfontcolor=:white)

# axis
hline!((0,0), color=:black, label="")
vline!((0,0), color=:black, label="")

# Scale values
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))

# Plot function
for i in 2:length(x)-1
plot!(x[i:i+1], [y[i], y[i]], label="", color=:blue, lw=2)
end
``````

Javier

1 Like

I actually tried this

``````using Plots, LaTeXStrings, Plots.PlotMeasures
gr()

f(x) = floor(x + 1/2)
x = -5:.5:4
y = f.(x)
plot(x[1:2], [y, y], 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
``````

and it returns error:

LoadError: Cannot convert Float64 to series data for plotting

seems the scatter function is problematic for using float or decimal value.

``````using Plots, LaTeXStrings, Plots.PlotMeasures
pyplot()

f(x) = floor(x + 1/2)
x = -5.5:1:4.5
y = f.(x)

plot(x[1:2], [y, y], label=L"f(x) = \lfloor x + 1/2 \rfloor", legend=:bottomleft,legend_foreground_color=:white,
legend_font_color=:blue, color=:blue, showaxis=false, tickfontcolor=:white)

# axis
hline!((0,0), color=:black, label="")
vline!((0,0), color=:black, label="")

# Scale values
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))

# Plot function
for i in 2:length(x)-1
plot!(x[i:i+1], [y[i], y[i]], label="", color=:blue, lw=2)
end
``````

the GUI window is not showing up, weird, but the REPL shows it is done…

`scatter` expects a vector of numbers, you need `scatter!([x[i]], [y[i]])` although at that point you might as well just pull it out of the loop and write `scatter!(x[2:length(x)-1], y[2:length(x)-1])` (which will also make the plot window show up as per my response in the other thread)

1 Like

I just read your reply more carefully and after lots of trial it works with this code:

``````using Plots; gr()

f(x) = floor(x + 1/2)
x = -5.5:1:4.5
y = f.(x)
plot(x[1:2], [y, y], label=L"f(x) = \lfloor x + 1/2 \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)
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="")
``````