Skip to content

Commit 85bd8ef

Browse files
moved the revised code into bar-charts.md from the notebook
1 parent 0770689 commit 85bd8ef

File tree

1 file changed

+53
-51
lines changed

1 file changed

+53
-51
lines changed

doc/python/bar-charts.md

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -597,82 +597,84 @@ This bar-style pictogram allows readers to focus on the relative sizes of smalle
597597
import plotly.graph_objects as go
598598
import pandas as pd
599599
600-
#TODO: make the results and the code compellingly clear, terse, and well designed; for example, make sure all the variable names are descriptive
601-
#TODO: when we're happy, remove print statements
602-
#TODO: consider adding the value for each group either above its section or to its title
603-
604-
def pictogram_bar(data, title, icon_size, max_height=10, units_per_icon=1,columns_between_units=.5):
605-
fig = go.Figure()
600+
def pictogram_bar(data, title, icon_size, max_height=10, units_per_icon=1, column_spacing=.75,icon_spacing=0.005):
606601
607-
# Iterate through the data and create a scatter plot for each category
602+
fig = go.Figure()
608603
x_start = 1
609604
tick_locations = []
610-
for i, (category, count) in enumerate(data.items()):
611-
#convert the real number input to an integer number of icons. Depending on the context, you might want to take floor or a ceiling rather than rouding
612-
count = round(count / units_per_icon)
613-
num_cols = (count + max_height - 1) // max_height # Ceiling division
614-
x_coordinates = []
615-
y_coordinates = []
616-
for col in range(num_cols):
617-
print([x_start+col]*min(max_height, count-col*max_height))
618-
x_coordinates += [x_start+col]*min(max_height, count-col*max_height)
619-
print(list(range(0, min(max_height, count-col*max_height))))
620-
for yc in range(1, min(max_height, count-col*max_height)+1):
621-
y_coordinates.append(yc)
622-
print(f"{category=}")
623-
print(f"{x_coordinates=}")
624-
print(f"{y_coordinates=}")
625-
# Add dots for this category
605+
606+
for i, (category, value) in enumerate(data.items()):
607+
icon_count = round(value / units_per_icon)
608+
num_columns = -(-icon_count // max_height) # Ceiling division
609+
610+
x_coordinates, y_coordinates = [], []
611+
for col in range(num_columns):
612+
column_icons = min(max_height, icon_count - col * max_height)
613+
x_coordinates.extend([x_start + col] * column_icons)
614+
y_coordinates.extend([y + icon_spacing * y for y in range(1, column_icons + 1)])
615+
616+
617+
# Add scatter plot for the category
626618
fig.add_trace(go.Scatter(
627-
x=x_coordinates, # All dots are in the same x position (category)
619+
x=x_coordinates,
628620
y=y_coordinates,
629621
mode='markers',
630-
marker=dict(size=icon_size, symbol="square", color=i),
622+
marker=dict(size=icon_size, symbol="square", color= i),
631623
name=category,
632-
#text=[category] * (y_end - y_start), # Hover text
633-
hoverinfo="text"
624+
hoverinfo="text",
625+
text=[f"{category}: {value}" for _ in range(len(x_coordinates))]
634626
))
635-
tick_locations += [x_start+ (col)/2]
636-
x_start += col+1+columns_between_units
637-
print(f"{tick_locations=}")
638-
639-
# Update layout for better visualization
627+
628+
629+
# Add value annotations above the section
630+
fig.add_trace(go.Scatter(
631+
x=[x_start + (num_columns - 1) / 2],
632+
y=[max_height + 1.2],
633+
mode="text",
634+
text=[f"{value}"],
635+
textfont=dict(size=14, color="black"),
636+
showlegend=False
637+
))
638+
639+
# Track tick locations
640+
tick_locations.append(x_start + (num_columns - 1) / 2)
641+
x_start += num_columns + column_spacing
642+
643+
# Update layout
640644
fig.update_layout(
641645
title=title,
642646
xaxis=dict(
643647
tickvals=tick_locations,
644648
ticktext=list(data.keys()),
645649
tickangle=-45,
646-
showgrid=False
650+
showgrid=False,
651+
title="Categories"
647652
),
648-
#TODO: HIDE THE Y-AXIS? OR ENUMERATE IT IN "NATURAL UNITS" -- so count
649653
yaxis=dict(
650-
title="Units",
654+
title=f"Units (1 icon = {units_per_icon})",
651655
showgrid=False,
652-
showline=False,
653-
zeroline=False
656+
zeroline=False,
654657
),
655-
#TO DO: SHOW THE LEGEND, BUT JUST FOR ONE TRACE; LABEL IT WITH SOMETHING LIKE "EACH ICON REPRESENTS {units_per_icon} {Y_VARNAME}"
656658
showlegend=False,
657-
#setting the width implicitly sets the amount of space between columns within groups and it's desirable to keep those columns close but not too close
658-
#TODO: set the width to a value that makes the spacing between columns reasonable; try it as a function of the number of columns of data, number of columns left blank as spacers, the icon size; and the left and right margins
659-
# there's no right answer; but some answers will look a lot better than others; I'm guessing that roughly 2-3 times as many px as we fill with icons might be good
660-
height=600
659+
height=600,
660+
width=(len(data) * 200 + 200)
661661
)
662662
663-
# Show the plot
664663
fig.show()
665664
666-
# TODO: CHANGE THIS THROUGHOUT TO A DF NAMED DF.
667665
668-
data = {
669-
"Haverford College": 1421, #https://www.usnews.com/best-colleges/haverford-college-3274
670-
"University of Mary Washington": 3611, #https://www.usnews.com/best-colleges/university-of-mary-washington-3746#:~:text=Overview,campus%20size%20is%20234%20acres.
671-
"Brown University": 7226, #https://oir.brown.edu/institutional-data/factbooks/enrollment
672-
"Arizona State University": 65174, #https://www.usnews.com/best-colleges/arizona-state-university-1081
673-
}
666+
df = pd.DataFrame({
667+
'School': ["Haverford College", "University of Mary Washington", "Brown University", "Arizona State University"],
668+
'Enrollment': [1421, 3611, 7226, 65174]
669+
})
674670
675-
pictogram_bar(data, title="Undergraduate Enrollment at Participating Schools", units_per_icon=1000, icon_size=27)
671+
pictogram_bar(
672+
data={row['School']: row['Enrollment'] for _, row in df.iterrows()},
673+
title="Undergraduate Enrollment at Participating Schools",
674+
units_per_icon=1000,
675+
icon_size=27,
676+
icon_spacing=0.05
677+
)
676678
```
677679

678680
### Customizing Individual Bar Base

0 commit comments

Comments
 (0)