From 54a68a310f48ba9d2201da1820c4abaf459154aa Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Fri, 28 Jun 2024 14:59:15 +0200 Subject: [PATCH] Add examples of how to create polar bar charts (#3428) --- .../polar_bar_chart.py | 62 +++++++++++++++++++ .../polar_bar_chart.py | 62 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 tests/examples_arguments_syntax/polar_bar_chart.py create mode 100644 tests/examples_methods_syntax/polar_bar_chart.py diff --git a/tests/examples_arguments_syntax/polar_bar_chart.py b/tests/examples_arguments_syntax/polar_bar_chart.py new file mode 100644 index 000000000..0d36bbd52 --- /dev/null +++ b/tests/examples_arguments_syntax/polar_bar_chart.py @@ -0,0 +1,62 @@ +""" +Polar Bar Chart +--------------- +This example shows how to make a polar bar chart using ``mark_arc``. +This could also have been called a "pie chart with axis labels", +but is more commonly referred to as a polar bar chart. +The axis lines are created using pie charts with only the stroke visible. +""" +# category: circular plots + +import math +import altair as alt +import pandas as pd + +source = pd.DataFrame({ + "hour": range(24), + "observations": [2, 2, 2, 2, 2, 3, 4, 4, 8, 8, 9, 7, 5, 6, 8, 8, 7, 7, 4, 3, 3, 2, 2, 2] +}) + +polar_bars = alt.Chart(source).mark_arc(stroke='white', tooltip=True).encode( + theta=alt.Theta("hour:O"), + radius=alt.Radius('observations', scale=alt.Scale(type='linear')), + radius2=alt.datum(1), +) + +# Create the circular axis lines for the number of observations +axis_rings = alt.Chart(pd.DataFrame({"ring": range(2, 11, 2)})).mark_arc(stroke='lightgrey', fill=None).encode( + theta=alt.value(2 * math.pi), + radius=alt.Radius('ring', stack=False) +) +axis_rings_labels = axis_rings.mark_text(color='grey', radiusOffset=5, align='left').encode( + text="ring", + theta=alt.value(math.pi / 4) +) + +# Create the straight axis lines for the time of the day +axis_lines = alt.Chart(pd.DataFrame({ + "radius": 10, + "theta": math.pi / 2, + 'hour': ['00:00', '06:00', '12:00', '18:00'] +})).mark_arc(stroke='lightgrey', fill=None).encode( + theta=alt.Theta('theta', stack=True), + radius=alt.Radius('radius'), + radius2=alt.datum(1), +) +axis_lines_labels = axis_lines.mark_text( + color='grey', + radiusOffset=5, + thetaOffset=-math.pi / 4, + # These adjustments could be left out with a larger radius offset, but they make the label positioning a bit clearner + align=alt.expr('datum.hour == "18:00" ? "right" : datum.hour == "06:00" ? "left" : "center"'), + baseline=alt.expr('datum.hour == "00:00" ? "bottom" : datum.hour == "12:00" ? "top" : "middle"'), + ).encode(text="hour") + +alt.layer( + axis_rings, + polar_bars, + axis_rings_labels, + axis_lines, + axis_lines_labels, + title=['Observations throughout the day', ''] +) diff --git a/tests/examples_methods_syntax/polar_bar_chart.py b/tests/examples_methods_syntax/polar_bar_chart.py new file mode 100644 index 000000000..fd59c52dc --- /dev/null +++ b/tests/examples_methods_syntax/polar_bar_chart.py @@ -0,0 +1,62 @@ +""" +Polar Bar Chart +--------------- +This example shows how to make a polar bar chart using ``mark_arc``. +This could also have been called a "pie chart with axis labels", +but is more commonly referred to as a polar bar chart. +The axis lines are created using pie charts with only the stroke visible. +""" +# category: circular plots + +import math +import altair as alt +import pandas as pd + +source = pd.DataFrame({ + "hour": range(24), + "observations": [2, 2, 2, 2, 2, 3, 4, 4, 8, 8, 9, 7, 5, 6, 8, 8, 7, 7, 4, 3, 3, 2, 2, 2] +}) + +polar_bars = alt.Chart(source).mark_arc(stroke='white', tooltip=True).encode( + theta=alt.Theta("hour:O"), + radius=alt.Radius('observations').scale(type='linear'), + radius2=alt.datum(1), +) + +# Create the circular axis lines for the number of observations +axis_rings = alt.Chart(pd.DataFrame({"ring": range(2, 11, 2)})).mark_arc(stroke='lightgrey', fill=None).encode( + theta=alt.value(2 * math.pi), + radius=alt.Radius('ring').stack(False) +) +axis_rings_labels = axis_rings.mark_text(color='grey', radiusOffset=5, align='left').encode( + text="ring", + theta=alt.value(math.pi / 4) +) + +# Create the straight axis lines for the time of the day +axis_lines = alt.Chart(pd.DataFrame({ + "radius": 10, + "theta": math.pi / 2, + 'hour': ['00:00', '06:00', '12:00', '18:00'] +})).mark_arc(stroke='lightgrey', fill=None).encode( + theta=alt.Theta('theta').stack(True), + radius=alt.Radius('radius'), + radius2=alt.datum(1), +) +axis_lines_labels = axis_lines.mark_text( + color='grey', + radiusOffset=5, + thetaOffset=-math.pi / 4, + # These adjustments could be left out with a larger radius offset, but they make the label positioning a bit clearner + align=alt.expr('datum.hour == "18:00" ? "right" : datum.hour == "06:00" ? "left" : "center"'), + baseline=alt.expr('datum.hour == "00:00" ? "bottom" : datum.hour == "12:00" ? "top" : "middle"'), + ).encode(text="hour") + +alt.layer( + axis_rings, + polar_bars, + axis_rings_labels, + axis_lines, + axis_lines_labels, + title=['Observations throughout the day', ''] +)