Plotting Function With if-else Using Gadfly.jl

I am trying to define and plot a density function. However, it seems the if-else logic of my function is not supported for this kind of plot. Am I doing something wrong?

## graph density of spinner
using Gadfly

function probDens(x::Real)
    if x >= 0 && x <=1
        6*x*(1-x)
    else
        x
    end
end

# plot(f::Function, lower, upper, elements...; mapping...)
plot(probDens,0,1)  ## works as expected
plot(probDens,-1,1)  ## gives error

This worked for me on Gadfly 1.3.2. Please include the error message and Gadfly version.

Thanks for the help. I am also on 1.3.2. Here is the error:

julia> Pkg.status("Gadfly")
Status `C:\Users\ajf\OneDrive\toolingForDS\Project.toml`
  [c91e804a] Gadfly v1.3.2

julia> plot(π_X,-1,1)  ## gives error
Error showing value of type Plot:
ERROR: MethodError: Cannot `convert` an object of type Nothing to an object of type Float64
Closest candidates are:
  convert(::Type{T}, ::Ratios.SimpleRatio{S}) where {T<:AbstractFloat, S} at C:\Users\ajf\.julia\packages\Ratios\uRs4y\src\Ratios.jl:13
  convert(::Type{T}, ::T) where T<:Number at number.jl:6
  convert(::Type{T}, ::Number) where T<:Number at number.jl:7
  ...
Stacktrace:
 [1] setindex!(::Array{Float64,1}, ::Nothing, ::Int64) at .\array.jl:847
 [2] apply_statistic(::Gadfly.Stat.FunctionStatistic, ::Dict{Symbol,Gadfly.ScaleElement}, ::Gadfly.Coord.Cartesian, ::Gadfly.Aesthetics) at C:\Users\ajf\.julia\packages\Gadfly\nN3lf\src\statistics.jl:1446
 [3] apply_statistics(::Array{Gadfly.StatisticElement,1}, ::Dict{Symbol,Gadfly.ScaleElement}, ::Gadfly.Coord.Cartesian, ::Gadfly.Aesthetics) at C:\Users\ajf\.julia\packages\Gadfly\nN3lf\src\statistics.jl:33
 [4] render_prepare(::Plot) at C:\Users\ajf\.julia\packages\Gadfly\nN3lf\src\Gadfly.jl:680
 [5] render(::Plot) at C:\Users\ajf\.julia\packages\Gadfly\nN3lf\src\Gadfly.jl:740
 [6] draw at C:\Users\ajf\.julia\packages\Gadfly\nN3lf\src\Gadfly.jl:847 [inlined]
 [7] show(::Base.GenericIOBuffer{Array{UInt8,1}}, ::MIME{Symbol("image/svg+xml")}, ::Plot) at C:\Users\ajf\.julia\packages\Gadfly\nN3lf\src\Gadfly.jl:945
 [8] display(::VSCodeServer.InlineDisplay, ::MIME{Symbol("image/svg+xml")}, ::Plot) at c:\Users\ajf\.vscode\extensions\julialang.language-julia-1.1.37\scripts\packages\VSCodeServer\src\display.jl:0
 [9] display(::VSCodeServer.InlineDisplay, ::String, ::Any) at .\multimedia.jl:216
 [10] display(::VSCodeServer.InlineDisplay, ::Plot) at c:\Users\ajf\.vscode\extensions\julialang.language-julia-1.1.37\scripts\packages\VSCodeServer\src\display.jl:108
 [11] display(::Any) at .\multimedia.jl:328
 [12] #invokelatest#1 at .\essentials.jl:710 [inlined]
 [13] invokelatest at .\essentials.jl:709 [inlined]
 [14] print_response(::IO, ::Any, ::Bool, ::Bool, ::Any) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\REPL\src\REPL.jl:238
 [15] print_response(::REPL.AbstractREPL, ::Any, ::Bool, ::Bool) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\REPL\src\REPL.jl:223
 [16] (::REPL.var"#do_respond#54"{Bool,Bool,REPL.var"#64#73"{REPL.LineEditREPL,REPL.REPLHistoryProvider},REPL.LineEditREPL,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\REPL\src\REPL.jl:822
 [17] #invokelatest#1 at .\essentials.jl:710 [inlined]
 [18] invokelatest at .\essentials.jl:709 [inlined]
 [19] run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\REPL\src\LineEdit.jl:2355
 [20] run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\REPL\src\REPL.jl:1144
 [21] (::REPL.var"#38#42"{REPL.LineEditREPL,REPL.REPLBackendRef})() at .\task.jl:356

If I experiment with a pdf from the Distributions.jl package, things seem to work.

using Distributions
densFun = function(x::Real)
    pdf(Beta(2,4),x)
end
plot(densFun,-1,2)  ## this works

What is your function π_X?

You are on the problem. When I name my function like this:

function π_X(x::Real)
    if x >= 0 && x <=1
        6*x*(1-x)
    else
        x
    end
end

I get the error. If I rename the function probDens, then it works. I renamed the function for the forum as to not seem too fancy. Lo and behold, it is the function name that is the issue. Do you know why?

You function π_X also works for me. I can’t reproduce the error in your post above.

Thanks for working with me on this. I restarted my Julia session and the bug goes away. I am pretty sure multiple dispatch is to blame. I originally typed the function argument x::Float64 and then switched to x::Real. I guess the incomplete function I wrote for Float64 took precedence over the complete one I wrote for x::Real.

Lessons Learned:

  1. Restart session and reproduce bug before posting
  2. Consider Revise.jl?

If there are other lessons to be learned … especially about using types, please share. Thanks :slight_smile:

2 Likes

I usually type function args only for dispatch purpose (or for clarity for exported functions in a public API).

Revise.jl is a must !

6x in place of 6*x and your function could nicely be written in one line

 π_Xb(x) = (x >= 0 && x <=1) ? 6x*(1-x) : x

Depending on the x distribution (if a branch is more probable and in this case which branch) this can be faster :wink:

 π_Xc(x) = (x < 0 || x >1) ? x : 6x*(1-x)
2 Likes