Skip to content

Commit 4bb0570

Browse files
Update bar-charts.md
1 parent 231edaa commit 4bb0570

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

doc/python/bar-charts.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,92 @@ fig.update_layout(
589589
)
590590
```
591591

592+
### Using a scatterplot to wrap long bars into multiple columns
593+
594+
This bar-style pictogram allows readers to focus on the relative sizes of smaller entities by wrapping the bar for largest entries into multiple columns. You could make it even more of a pictogram by using fontawesome to replace the square markers we use below with icons like mortar boards for students.
595+
596+
```
597+
import plotly.graph_objects as go
598+
import pandas as pd
599+
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()
606+
607+
# Iterate through the data and create a scatter plot for each category
608+
x_start = 1
609+
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
626+
fig.add_trace(go.Scatter(
627+
x=x_coordinates, # All dots are in the same x position (category)
628+
y=y_coordinates,
629+
mode='markers',
630+
marker=dict(size=icon_size, symbol="square", color=i),
631+
name=category,
632+
#text=[category] * (y_end - y_start), # Hover text
633+
hoverinfo="text"
634+
))
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
640+
fig.update_layout(
641+
title=title,
642+
xaxis=dict(
643+
tickvals=tick_locations,
644+
ticktext=list(data.keys()),
645+
tickangle=-45,
646+
showgrid=False
647+
),
648+
#TODO: HIDE THE Y-AXIS? OR ENUMERATE IT IN "NATURAL UNITS" -- so count
649+
yaxis=dict(
650+
title="Units",
651+
showgrid=False,
652+
showline=False,
653+
zeroline=False
654+
),
655+
#TO DO: SHOW THE LEGEND, BUT JUST FOR ONE TRACE; LABEL IT WITH SOMETHING LIKE "EACH ICON REPRESENTS {units_per_icon} {Y_VARNAME}"
656+
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
661+
)
662+
663+
# Show the plot
664+
fig.show()
665+
666+
# TODO: CHANGE THIS THROUGHOUT TO A DF NAMED DF.
667+
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+
}
674+
675+
pictogram_bar(data, title="Undergraduate Enrollment at Participating Schools", units_per_icon=1000, icon_size=27)
676+
```
677+
592678
### Customizing Individual Bar Base
593679

594680
```python

0 commit comments

Comments
 (0)