@@ -603,26 +603,25 @@ def pictogram_bar(data, title, icon_size, max_icons_per_column=10, units_per_ico
603
603
tick_locations = []
604
604
# loop through each group and create a trace with its icons
605
605
for i, (category, value) in enumerate (data.items()):
606
- # compute the number of icons represent this category
606
+ # compute the number of icons to use to represent this category. Depending on your use case, you might replace round with floor or ceiling.
607
607
icon_count = round (value / units_per_icon)
608
- # compute the number of columns in which to arrange this category
609
- # every category gets at least one column; we use integer division
610
- # to compute the number of additional columns
611
- num_columns = (icon_count // max_icons_per_column)+ 1
608
+ # compute the number of columns in which to arrange the icons for this category
609
+ # using a double negative sign to convert a floor(division) operation into a ceiling(division) operation
610
+ num_columns = - (- icon_count // max_icons_per_column)
612
611
613
- # create lists of coordinates and populate them
612
+ # create and populate lists of icon coordinates
614
613
x_coordinates, y_coordinates = [], []
615
614
for col in range (num_columns):
616
615
# the number of icons in this column is the lesser of the column height or
617
616
# the number of icons remaining to place
618
617
column_icons = min (max_icons_per_column, icon_count - col * max_icons_per_column)
619
618
620
- # create a list element containing the x-coordinate of this column;
621
- # add column_icons copies of that coordinate to the list of icon x coordinates
622
- # normalizing the width of each within group column to 1 simplifies the code
623
- # we can adjust the visible space between columns by adjusting the total width below
619
+ # Create a one item list containing the x-coordinate of this column.
620
+ # Then add column_icons copies of that coordinate to the list of icon x coordinates using list multiplication.
621
+ # Normalizing the width of each within-category column to 1 simplifies the code.
622
+ # We can adjust the visible space between columns by adjusting the total width below.
624
623
x_coordinates.extend([x_start + col] * column_icons)
625
- # create a list of sequentially increasing y-coordinates for icons
624
+ # Create a list of sequentially increasing y-coordinates for icons.
626
625
y_coordinates.extend([y + icon_vertical_spacing * y for y in range (1 , column_icons + 1 )])
627
626
# Add scatter plot for the category
628
627
fig.add_trace(go.Scatter(
@@ -631,43 +630,48 @@ def pictogram_bar(data, title, icon_size, max_icons_per_column=10, units_per_ico
631
630
mode = ' markers' ,
632
631
marker = dict (size = icon_size, symbol = " square" , color = i),
633
632
name = category,
634
- # suppress the x and y coordinates in the hover text, since they are meaningless to readers
633
+ # Suppress the x and y coordinates in the hover text, since they are irrelevant implementation details.
635
634
hoverinfo = " text" ,
636
635
text = [f " { category} : { value} " for _ in range (len (x_coordinates))]
637
636
))
638
637
639
- # add an annotation above the center of each section showing its value
638
+ # Add an annotation above the center of each category showing its value
640
639
fig.add_trace(go.Scatter(
641
- x = [x_start + (num_columns - 1 ) / 2 ], # center
642
- y = [max_icons_per_column + 1.2 ],
640
+ x = [x_start + (num_columns - 1 ) / 2 ], # Compute the location of the center
641
+ y = [max_icons_per_column* ( 1 + icon_vertical_spacing) + 1.15 ],
643
642
mode = " text" ,
644
643
text = [f " { value} " ],
645
644
textfont = dict (size = 14 , color = " black" ),
646
645
showlegend = False
647
646
))
648
- # Track locations where we will put the text for each category
647
+ # Track locations where we will put the text labeling each category
649
648
tick_locations.append(x_start + (num_columns - 1 ) / 2 )
650
649
# compute the left edge of the next category
651
650
x_start += num_columns + inter_group_spacing
652
- # Update layout
651
+
653
652
fig.update_layout(
654
653
title = title,
655
654
xaxis = dict (
656
655
tickvals = tick_locations,
656
+ # Label ecah category
657
657
ticktext = list (data.keys()),
658
658
tickangle = - 45 ,
659
659
showgrid = False ,
660
660
title = " Categories"
661
661
),
662
662
yaxis = dict (
663
- title = f " Units (1 icon = { units_per_icon:,g } { unit_description} ) " ,
663
+ title = f " Each icon represents { units_per_icon:,g } { unit_description} " ,
664
+ # The y-axis goes above the top icon to make room for the annotations.
665
+ # We set tick values so the axis labeling does not go above the top icon.
666
+ # If you choose a value of max_icons_per_column that is not a multiple of 5, consider changing this.
667
+ tickvals = list (range (0 ,max_icons_per_column+ 1 ,5 )),
664
668
showgrid = False ,
665
669
zeroline = False ,
666
670
),
667
- # we've got all the labeling we need without a legend
671
+ # We have already got all the labeling we need so we suppress the legend.
668
672
showlegend = False ,
669
673
height = 700 ,
670
- # the x-coordinates scale to fill available space, so adjusting the width of the image is a good way to adjust spacing between columns
674
+ # The x-coordinates scale to fill available space, so adjusting the width of the image is a good way to adjust spacing between columns.
671
675
width = (len (data) * 150 + 50 )
672
676
)
673
677
fig.show()
0 commit comments