2

I don't like the way Gadfly chooses axis limits when plotting, for example one of the plots I produced only had data in the center quarter of the canvas. A MWE could be:

plot(x=[2.9,8.01],y=[-0.01,0.81])

screenshot of above plot Gadfly then picks an x-axis range of [0,10] and [-0.5,1] for the y-axis, which both seem far too wide for me. The values here are obviously made up, but are basically the bounding box of my real data.

I'd much prefer not to have all that blank space, something like R's default 4% mode (i.e. par(xaxs='r',yaxs='r')). I can get something similar in Gadfly by doing:

plot(x=[2.9,8.01],y=[-0.01,0.81]
  Guide.xticks(ticks=[3:8]),
  Guide.yticks(ticks=[0:0.2:0.8]))

i.e. screenshot of second example

Does something like this already exist in Gadfly? Given that I struggled to find Guide.[xy]ticks I'm expecting that I'll need to write some code for this…

Pointers appreciated!

Sam Mason
  • 15,216
  • 1
  • 41
  • 60

1 Answers1

1

As a work around, I've got an altered version of Heckbert's 1990's Graphics Gems code working to generate ticks within a given min/max. It looks like this in (my naïve) Julia:

# find a "nice" number approximately equal to x.
# round the number if round=true, take the ceiling if round=false
function nicenum{T<:FloatingPoint}(x::T, round::Bool)
    ex::T = 10^floor(log10(x))
    f::T = x/ex
    convert(T, if round
        if     f < 1.5; 1.
        elseif f < 3.;  2.
        elseif f < 7.;  5.
        else;           10.
        end
    else
        if     f <= 1.; 1.
        elseif f <= 2.; 2.
        elseif f <= 5.; 5.
        else;           10.
        end
    end)*ex
end

function pretty_inner{T<:FloatingPoint}(min::T, max::T, ntick::Int)
    if max < min
        error("min must be less than max")
    end
    if min == max
        return min:one(T):min
    end
    delta = nicenum((max-min)/(ntick-1),false)
    gmin =  ceil(min/delta)*delta
    gmax = floor(max/delta)*delta
    # shift max a bit in case of rounding errors
    gmin:delta:(gmax+delta*eps(T))
end

and can be used as:

plot(x=[2.9,8.01],y=[-0.01,0.81],
  Guide.xticks(ticks=[pretty_inner(2.9,8.01,7)]),
  Guide.yticks(ticks=[pretty_inner(-0.01,0.81,7)]))

and will give the same result as I got from R.

It would be great if the ranges could be pulled out automatically, but I can't see how to do that within the existing Gadfly code.

Sam Mason
  • 15,216
  • 1
  • 41
  • 60