Skip to content

[MNT]: DISCUSSION: Should Axes.grouped_bar() apply a default hatch pattern when none is provided? #30728

Closed as not planned

Description

@ilakkmanoharan

Summary

Currently, when no hatch argument is passed to Axes.grouped_bar(), hatching is entirely disabled:

if hatch is None:
    # No hatch specified: disable hatching entirely by cycling [None].
    hatches = itertools.cycle([None])
    # TODO: Discussion —
    #   Should grouped_bar() apply a default hatch pattern (e.g., '//')
    #   when none is provided ?

This behavior matches the philosophy of “explicit is better than implicit,” keeping hatching opt-in.
However, there’s a possible usability question:
Should grouped_bar() automatically apply a default hatch pattern (for example '//') when multiple datasets are plotted, to help users visually distinguish bars even when colors are similar or when figures are printed in grayscale?

Discussion Points:

Would automatic hatching improve accessibility and readability (especially in black-and-white printing)?
Should the default depend on the number of datasets or color distinctness?

Follow-up to the Enh/Add hatch pattern support to Axes.grouped_bar #30726

Proposed fix

No response

Activity

  1. story645 commented on Nov 5, 2025

    @story645
    Member

    Should grouped_bar() automatically apply a default hatch pattern (for example '//') when multiple datasets are plotted, to help users visually distinguish bars even when colors are similar or when figures are printed in grayscale?

    No, it should default to no hatch because that matches the behavior of histogram and stack plot, which are the other methods that plot multiple datasets using area (bars and filled curves) respectively.

  2. timhoffm commented on Nov 5, 2025

    @timhoffm
    Member

    I've answered this already in #30726 (comment).

    Also, this is a fundamental behavior of the functionality of the PR. It should be primarily discussed there (if there was anything left to discuss). Please do not pull related discussions aparat by excessively opening discussion issues that are in the scope of the PR (like this and #30729).

  3. rcomer commented on Nov 5, 2025

    @rcomer
    Member

    Should grouped_bar() automatically apply a default hatch pattern (for example '//') when multiple datasets are plotted, to help users visually distinguish bars even when colors are similar or when figures are printed in grayscale?

    A single hatch pattern applied to all bars logically would not distinguish them.

  4. ilakkmanoharan commented on Nov 5, 2025

    @ilakkmanoharan
    ContributorAuthor

    @timhoffm @story645 @rcomer

    Current behavior of colors and hatch:

    When colors=None:

    Matplotlib automatically cycles through the property color cycle (axes.prop_cycle), giving each dataset a distinct color by default.

    When colors is a single string (e.g. 'blue'):

    Since strings are iterable, itertools.cycle('blue') will incorrectly iterate over the characters 'b', 'l', 'u', 'e', producing unintended results.

    To apply one color to all datasets, use a single-element list, like ['blue'].

    When colors is a single-element list (e.g. ['blue']):

    The same color is applied to all datasets.

    When colors is a sequence (e.g. ['#1f77b4', '#ff7f0e', '#2ca02c']):

    The sequence is wrapped in itertools.cycle(colors).

    If there are more datasets than colors, the list repeats from the beginning, cycling through the same colors again.

    If there are fewer datasets than colors, only the needed colors are used; the extra colors are ignored.

    This behavior matches how color lists work in bar() and stackplot().

    When colors is an empty list ([]):

    Treated as None, so the default property color cycle is used.

    When colors is a non-iterable (e.g. 123):

    A TypeError occurs since it cannot be cycled.

    For hatch:

    When hatch=None:

    Hatching is disabled entirely (itertools.cycle([None])), making hatching explicitly opt-in.

    When hatch is a single string (e.g. '//'):

    Raises a ValueError:

    "‘hatch’ must be a sequence of strings (e.g., ['//']) or None; a single string like '//' is not allowed."

    This prevents accidental iteration over individual characters ('/', '/').

    When hatch is a single-element list (e.g. ['//']):

    The same hatch pattern is applied to all datasets.

    Because the list is wrapped with itertools.cycle(hatch), it repeats the single entry indefinitely — so every dataset receives '//'.
    This is intentional and valid, unlike passing '//' as a plain string (which raises a ValueError).

    Users can use this form to apply one uniform hatch pattern across all datasets.

    When hatch is a sequence of strings (e.g. ['//', 'xx', '..']):

    The sequence is wrapped in itertools.cycle(hatch).

    If there are more datasets than hatch patterns, the patterns repeat from the beginning, cycling through the same sequence again.

    If there are fewer datasets than hatch patterns, only the first few are used; the extras are ignored.

    This allows flexible per-dataset hatching without enforcing strict length matching.

    When hatch is an empty list ([]):

    Treated as None, disabling hatching.

    When hatch is non-iterable (e.g. 123):

    Raises a ValueError, since it cannot be converted into a sequence.

    When hatch contains non-string entries (e.g. [1, 2, 3]):

    Raises a TypeError — all entries must be strings representing valid hatch patterns.

  5. ilakkmanoharan commented on Nov 5, 2025

    @ilakkmanoharan
    ContributorAuthor

    Should grouped_bar() automatically apply a default hatch pattern (for example '//') when multiple datasets are plotted, to help users visually distinguish bars even when colors are similar or when figures are printed in grayscale?

    A single hatch pattern applied to all bars logically would not distinguish them.

    When hatch is a single-element list (e.g. ['//']):

    The same hatch pattern is applied to all datasets.

    When colors is a single-element list (e.g. ['blue']):

    The same color is applied to all datasets.

    So we already have this behavior -->>> A single hatch pattern applied to all bars

    Also, we can also choose to provide a sequence of default hatch patterns if needed.

  6. ilakkmanoharan commented on Nov 5, 2025

    @ilakkmanoharan
    ContributorAuthor

    I've answered this already in #30726 (comment).

    Also, this is a fundamental behavior of the functionality of the PR. It should be primarily discussed there (if there was anything left to discuss). Please do not pull related discussions aparat by excessively opening discussion issues that are in the scope of the PR (like this and #30729).

    When colors=None:

    Matplotlib automatically cycles through the property color cycle (axes.prop_cycle), giving each dataset a distinct color by default.

    When colors is an empty list ([]):

    Treated as None, so the default property color cycle is used.

    So I wanted to mimic the same behavior for hatch too

  7. timhoffm commented on Nov 5, 2025

    @timhoffm
    Member

    @ilakkmanoharan I'm sorry, I won't read #30728 (comment). It's a long list of current behavior descriptions - i.e. lots of detail but no scoping and communication of intent. You've lost me here.

    If you want attention, please communicate more concisely. A few well-crafted sentences can communicate a lot more. I accidentally happen to have read your last sentence in the previous post. It seems this was your overall topic, and a single sentence would have been sufficient:

    Should hatching in grouped_bar follow the property-cycle, as color does.

  8. ilakkmanoharan commented on Nov 5, 2025

    @ilakkmanoharan
    ContributorAuthor

    @ilakkmanoharan I'm sorry, I won't read #30728 (comment). It's a long list of current behavior descriptions - i.e. lots of detail but no scoping and communication of intent. You've lost me here.

    If you want attention, please communicate more concisely. A few well-crafted sentences can communicate a lot more. I accidentally happen to have read your last sentence in the previous post. It seems this was your overall topic, and a single sentence would have been sufficient:

    Should hatching in grouped_bar follow the property-cycle, as color does.

    Yes! Absolutely!! Should hatching in grouped_bar follow the property-cycle, as color does.-->>> this is what I wanted to communicate but I wanted to be more clear.

  9. story645 commented on Nov 5, 2025

    @story645
    Member

    is what I wanted to communicate but I wanted to be more clear.

    What's currently happening is folks are instead getting completely lost in your comments. What I suggest going forward is that you post the overview/big picture question and only provide details as/if requested. If you feel you need to provide details to get your point across, please first have one sentence explaining why you are posting these details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions