Skip to content

Free facet dimensions get the globally resolved breaks, so most panels show one tick #516

Description

@thomasp85

Summary

ggsql resolves exactly one scale — and one break set — per aesthetic, including for a facet dimension declared free. The Vega-Lite writer therefore pins the global break set as axis.values even where it has delegated the domain to Vega, so each free panel shows only whichever global breaks happen to fall inside it — frequently one, or none.

While this issue is about the breaks specifically, it also points to a deficiency in our ggsql <-> writer contract. Specifically for faceted plots with free scales we are currently letting the writer calculate range, breaks etc for the free scales. This really belongs in ggsql which should resolve the scale to an array somehow (VegaLite might not be able to consume that but Hephaestus can)

Reproduction

VISUALISE Date AS x, Temp AS y FROM ggsql:airquality
DRAW line
FACET Month SETTING free => 'x'
resolve: {'scale': {'x': 'independent'}}     # domain correctly delegated to Vega
scale:   {'zero': False}                     # no domain, as intended
values:  ['1973-04-23', '1973-05-21', '1973-06-18', '1973-07-16', '1973-08-13', '1973-09-10']

Those six breaks span the whole year, but each panel covers one month — so a panel gets at most one of them.

Why it belongs in core

Both writers currently work around the missing per-panel resolution, in different places and with different results:

  • Vega-Lite delegates the domain to Vega (resolve.scale: independent) but still pins global break values on top of it.
  • hephaestus computes the per-panel extent itself in scales::free_position_scale / free_binned_scale, applying ggsql's own Scale::expand_range factors — this is the one remaining piece of writer-side domain computation, and it exists solely because core resolves nothing per panel.

Resolving per-panel domains and breaks for a free facet dimension in core fixes the Vega-Lite tick problem and removes the hephaestus writer's architectural exception in one go.

Activity

  1. teunbrand commented on Aug 13, 2026

    @teunbrand
    Collaborator

    I agree break and label calculations should be in core (if that is what we're calling the bits and bobs before data enters the writer).
    Internally using an array of scales sounds perfectly reasonable to me, but I may need to be convinced that we shouldn't let users specify individual scales directly.

  2. thomasp85 commented on Aug 14, 2026

    @thomasp85
    CollaboratorAuthor

    I'm happy with the latter insofar that we can come up with a non-horrible syntax for it. So far we have been unsuccessful on the ggplot2 side I think

  3. added
    writerConcerns the writer arm of ggsql.
    plot buildingIn between the reader and writer, execution of plot logic
    on Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    plot buildingIn between the reader and writer, execution of plot logicwriterConcerns the writer arm of ggsql.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions