Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added side-by-side categorical hist plotting example #153

Merged
merged 9 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/basics/1d_hist.rst
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,17 @@ String category
.. image:: ../img/1d_str_category.svg
:alt: String category plot
:width: 500


Side-by-side histograms
-----------------------

Here is an example to put three histograms side by side with a categorical axis and boost-histogram:

.. literalinclude:: ../examples/1d_hist/1d_side_by_side.py
:language: python
:start-after: ###

.. image:: ../img/1d_side_by_side.svg
:alt: Side by side histograms
:width: 500
83 changes: 83 additions & 0 deletions docs/examples/1d_hist/1d_side_by_side.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
1d side by side
===============

Plot multiple 1d histogram with categories side by side.
0ctagon marked this conversation as resolved.
Show resolved Hide resolved

"""

###
import boost_histogram as bh
import numpy as np
import matplotlib.pyplot as plt
import plothist # For the style
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is only for the style, does it belong to the plothist documentation? Especially in the first page of the documentation (1D histograms)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can discuss, for now I move it to Other complex examples section. I really like having this plot in the gallery, and it is much easier to do with boost-histogram than matplotlib.


np.random.seed(8311311)
0ctagon marked this conversation as resolved.
Show resolved Hide resolved

# Integer categories
categories = ["A", "B", "C"]
## Work also with integers
# categories = [-5, 10, 137]

# Axis with the 3 bins
axis = bh.axis.StrCategory(categories=categories)

# Generate data for 3 histograms
data = [
np.random.choice(categories, 15),
np.random.choice(categories, 15),
np.random.choice(categories, 15),
]

# Create and fill the histograms
histos = [bh.Histogram(axis, storage=bh.storage.Weight()) for _ in range(len(data))]
histos = [histo.fill(data[i]) for i, histo in enumerate(histos)]

# Convert the histograms to numpy arrays
histo_arrays = [histo.values() for histo in histos]
0ctagon marked this conversation as resolved.
Show resolved Hide resolved

# Create an array for the x-coordinates of the bars
x = np.arange(len(axis))


# Get the correct shift for each bar
def calculate_shifts(width, n_bars):
half_width = width / 2
shift = np.linspace(-half_width, half_width, n_bars, endpoint=False)
shift += width / (2 * n_bars)
return shift


bin_width = 0.7
0ctagon marked this conversation as resolved.
Show resolved Hide resolved
n_bars = len(histos)
shift = calculate_shifts(bin_width, n_bars)

fig, ax = plt.subplots()

# Plot the histograms side by side
for i, histo in enumerate(histo_arrays):
bars = ax.bar(
x + shift[i], histo, width=bin_width / n_bars, label=f"$\mathit{{h_{i}}}$"
)

# Optional: Add the number on top of each bar
0ctagon marked this conversation as resolved.
Show resolved Hide resolved
for bar in bars:
height = bar.get_height()
ax.text(
bar.get_x() + bar.get_width() / 2,
height + 0.1,
0ctagon marked this conversation as resolved.
Show resolved Hide resolved
int(height),
0ctagon marked this conversation as resolved.
Show resolved Hide resolved
ha="center",
va="bottom",
)

# Label the x-ticks with the categories
ax.set_xticks(x, axis)
ax.set_ylim(top=np.max([np.max(histo) for histo in histo_arrays]) + 2)
0ctagon marked this conversation as resolved.
Show resolved Hide resolved
ax.minorticks_off()

ax.set_ylabel("Entries")
ax.set_xlabel("Categories")
ax.legend()

fig.savefig("1d_side_by_side.svg", bbox_inches="tight")
Loading
Loading