Pitfalls#

This page collects limitations that can otherwise produce plausible but incorrect figures, following the prominent pitfalls guidance used by statsmodels.

Coordinate transforms on collapsed axes#

Collapsed mode is a registered matplotlib x-scale. Ordinary ax.transData artists and public blended transforms with an x-data component, including ax.axvline(timestamp), pass through that scale. Axes-, figure-, display-, and custom transforms do not automatically become date-bearing; use native matplotlib semantics for those coordinate systems.

Collection observation discovery#

Lines, scatter collections, and fill_between polygons retain matplotlib date numbers and render correctly before or after collapse. All three contribute observations automatically. Polygon discovery reads only the source-side vertices of each native fill_between path. Closing vertices and boundaries generated by interpolate=True never become observations; masks, NaNs, and where=False regions do not contribute because Matplotlib omits them from the retained paths.

Matplotlib does not retain enough information to recover the original interior dates from step="mid" polygons. Supply the complete source sequence explicitly for that form:

handle = gs.dates(ax, data=dates).collapse()

fill_betweenx remains unsupported on an x-date handle, and polygon transforms other than ax.transData fail with ggstyle.DateDiscoveryError. These checks happen before a registry revision is committed.

Dates between observations#

ggstyle.DateAxis.loc() interpolates a missing date between neighboring observations. Use snap=True to select the nearest observation or strict=True to reject dates that were not observed.

Timezone display#

Timezone-aware inputs are converted to naive UTC instants for positioning. ggstyle.DateAxis.tz() changes labels only. For naive input, display-timezone conversion assumes that the original values represent UTC.

Input interpretation#

Whole data frames, scalar dates, and string-typed pandas or polars columns are rejected. Select one column and convert it to a datetime dtype explicitly. This prevents accidental interpretation of identifiers or ambiguous date strings.

Missing explicit dates#

Explicit data containing missing dates raises by default. missing="drop" excludes those values and records their count in ggstyle.DateAxis.summary(). Missing x-values already present in a line are treated as intentional line breaks and are not counted.

Synchronized collapsed panels#

Calling ggstyle.DateAxis.collapse() independently on several panels can assign different ordinal positions to the same date. Use ggstyle.sync_dates() when panels are intended for comparison.

Synchronization uses one live, revisioned registry. After changing plotted artists, call ggstyle.DateAxis.refresh() on any member. The refresh rescans every member and updates their transforms in one transaction while preserving view limits.

Refresh boundaries#

Refresh discovers ordinary data-space lines and scatter offsets. A date-bearing line or scatter collection using a custom x transform is rejected with ggstyle.DateDiscoveryError; ggstyle does not guess whether arbitrary display or axes coordinates are dates. Native axvline blended transforms and ggstyle-managed annotations and grids are presentation elements and do not contribute observations.

Native fill_between polygons are also discovered when their vertices use ax.transData. Arbitrary third-party collection subclasses are not accepted. Version 0.3 uses strict exceptions only and has no permissive warning mode.

Raw numeric coordinates on an axes whose date converter was installed by another artist remain inherently ambiguous. Supply complete explicit data= whenever numeric values are intended to represent date numbers.

Existing-axes themes#

An rcParams theme fully controls artists created inside its context. Applying a theme later through ggstyle.finish() changes only properties that are safely retroactive. It does not recolour data, replace the axes property cycle, resize the figure, or rewrite line defaults. Inspect result.diagnostics or a dry-run plan for the preserved creation-, data-, and output-time settings.

Direct-label eligibility#

Endpoint labels use public legend participation, so labels beginning with an underscore are ignored. Every visible participant must be an ordinary data-transform Line2D on a rectilinear axes. A mixed line/scatter plot does not receive a misleading partial set: it falls back wholly to a legend by default or raises when fallback="raise".

Semantic-guide ownership#

ggstyle.guides() preserves caller-owned legends and colorbars and manages only the objects returned in ggstyle.GuideResult. Consequently ax.get_legend() still refers to the caller-owned axes legend; use result.legends for semantic legends. Passing enabled=False removes managed semantic guides without touching native ones. Automatic layout is capped at four distinct legends and four distinct colorbars on one axes. Use facets or explicit Matplotlib guides beyond that boundary.

Semantic frame inputs#

Semantic helpers accept named one-dimensional columns from pandas, Polars, and ordinary mapping-like frames without mutating the input. Materialize a Polars LazyFrame with collect() first. Duplicate column names, unequal column lengths, and expression-like arguments are rejected rather than guessed. Numeric color is continuous by default; pass ggstyle.DiscreteScale when numeric codes represent categories. A continuous color must be constant within each resolved line or ribbon because each native artist has one color, while points may vary per observation.

Figure export#

ggstyle.save() refuses to overwrite by default and never creates parent directories. Tight bounds crop the nominal canvas around decorated content; use bbox="standard" when exact raster dimensions are the contract. Metadata support is defined by the selected Matplotlib backend rather than normalized across formats.