title: How to create "100% stacked" bar charts in plotly?
body: <p>I am trying to generate a stacked bar chart with plotly, specifically one that is &quot;100%-stacked,&quot; like this:-</p>
  <p><a href="https://www.python-graph-gallery.com/13-percent-stacked-barplot" rel="nofollow noreferrer">https://www.python-graph-gallery.com/13-percent-stacked-barplot</a></p>
  <p>I am using the following code:-</p>
  <pre><code>import plotly
  import plotly.graph_objects as go
  import numpy as np
  binnum_attr=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
  tnl_attr=[164549.654, 278570.473, 201857.2155, 146326.9935, 116167.091, 98121.201, 384025.989, 786854.992, 502627.797, 306844.9995, 452795.6745, 271533.2325, 143591.5138]
  pop_attr=[296699, 195322, 82853, 42382, 26001, 17926, 47187, 46586, 15508, 6500, 6412, 2339, 785]
  verbose_customdata = np.stack((binnum_attr, tnl_attr, pop_attr), axis=-1)
  
  fig = go.Figure(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['3.618', '1.526', '0.899', '0.674', '0.587', '0.566', '0.632', '0.411', '0.139', '0.081', '0.046', '0.024', '0.060'], customdata=verbose_customdata, legendgroup=&quot;M0&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M0 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M0', marker_color='rgb(128,128,128)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['36.797', '21.312', '12.348', '9.136', '8.275', '8.028', '9.105', '5.944', '2.473', '1.225', '0.725', '0.394', '0.377'], customdata=verbose_customdata, legendgroup=&quot;M1&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M1 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M1', marker_color='rgb(230,25,75)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['45.265', '40.620', '30.699', '23.548', '20.190', '18.252', '18.068', '13.085', '6.579', '3.656', '1.950', '1.343', '2.040'], customdata=verbose_customdata, legendgroup=&quot;M2&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M2 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M2', marker_color='rgb(60,180,75)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['12.552', '28.142', '34.866', '33.760', '30.362', '27.477', '22.317', '16.624', '10.221', '6.285', '3.853', '2.342', '3.101'], customdata=verbose_customdata, legendgroup=&quot;M3&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M3 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M3', marker_color='rgb(0,130,200)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['1.572', '7.198', '17.117', '24.482', '27.654', '28.867', '27.013', '22.357', '16.369', '13.342', '9.081', '6.584', '7.308'], customdata=verbose_customdata, legendgroup=&quot;M4&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M4 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M4', marker_color='rgb(245,130,48)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.177', '1.028', '3.369', '7.020', '10.741', '13.425', '16.108', '16.946', '13.654', '11.075', '7.060', '3.919', '3.424'], customdata=verbose_customdata, legendgroup=&quot;M5&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M5 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M5', marker_color='rgb(145,30,180)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.014', '0.147', '0.539', '0.898', '1.445', '2.123', '3.598', '7.842', '8.837', '7.916', '6.015', '4.466', '4.884'], customdata=verbose_customdata, legendgroup=&quot;M6&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M6 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M6', marker_color='rgb(70,240,240)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.003', '0.012', '0.120', '0.309', '0.460', '0.801', '2.013', '7.288', '10.854', '10.506', '6.766', '3.984', '2.921'], customdata=verbose_customdata, legendgroup=&quot;M7&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M7 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M7', marker_color='rgb(0,0,128)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.000', '0.001', '0.018', '0.075', '0.142', '0.279', '0.579', '4.052', '9.357', '10.690', '11.111', '9.456', '8.756'], customdata=verbose_customdata, legendgroup=&quot;M8&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M8 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M8', marker_color='rgb(210,245,80)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.003', '0.010', '0.019', '0.043', '0.086', '0.103', '0.300', '2.427', '7.132', '9.093', '8.937', '7.208', '4.578'], customdata=verbose_customdata, legendgroup=&quot;M9&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M9 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M9', marker_color='rgb(0,128,128)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.000', '0.000', '0.002', '0.017', '0.033', '0.051', '0.149', '1.564', '5.752', '9.613', '12.453', '15.218', '13.762'], customdata=verbose_customdata, legendgroup=&quot;M10&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M10 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M10', marker_color='rgb(220,190,255)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.000', '0.003', '0.004', '0.028', '0.019', '0.022', '0.068', '0.558', '3.286', '5.387', '9.235', '9.583', '6.008'], customdata=verbose_customdata, legendgroup=&quot;M11&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M11 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M11', marker_color='rgb(170,255,195)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.000', '0.000', '0.000', '0.002', '0.001', '0.001', '0.036', '0.732', '4.020', '8.839', '15.911', '25.388', '20.153'], customdata=verbose_customdata, legendgroup=&quot;M12&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M12 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M12', marker_color='rgb(255,215,180)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.000', '0.000', '0.000', '0.003', '0.003', '0.005', '0.014', '0.119', '0.810', '1.324', '3.969', '5.143', '7.068'], customdata=verbose_customdata, legendgroup=&quot;M13&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M13 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M13', marker_color='rgb(0,0,0)', marker_opacity=1.0))
  fig.add_trace(go.Bar(x=['0~1', '1~2', '2~3', '3~4', '4~5', '5~6', '6~11', '11~26', '26~41', '41~55', '55~94', '94~158', '158~1644'], y=['0.000', '0.000', '0.000', '0.004', '0.000', '0.000', '0.000', '0.050', '0.517', '0.967', '2.888', '4.948', '15.559'], customdata=verbose_customdata, legendgroup=&quot;M14&quot;, hovertemplate='&lt;b&gt;Bin: %{customdata[0]: .0f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;M14 portion: %{y:.2f}%&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Total length (all layers): %{customdata[1]:.2f}&lt;/b&gt;&lt;br&gt;'+'&lt;b&gt;Nets: %{customdata[2]: .0f}&lt;/b&gt;&lt;br&gt;', name='M14', marker_color='rgb(128,0,0)', marker_opacity=1.0))
  fig.update_layout(barmode='stack')
  fig.update_layout(title_text='&lt;b&gt;Metal Layer Usage by Length: euunit n3&lt;/b&gt;', title_font_size=28, yaxis=dict(title='&lt;b&gt;Metal Layer Usage (%)&lt;/b&gt;', titlefont_size=20, showticklabels=False), xaxis=dict(title='&lt;b&gt;Net Length Range (um)&lt;/b&gt;', titlefont_size=20, tickfont_size=16))
  fig.update_layout(legend=dict(font=dict(size=14),borderwidth=1))
  fig.show()
  </code></pre>
  <p>...however, the outcome looks like this:-</p>
  <p><a href="https://i.stack.imgur.com/DjS9b.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/DjS9b.png" alt="not 100 percent stacked bar" /></a></p>
  <p>...I am not quite sure why the bars do not fully occupy the vertical height of the plot area. Does the sum total of numbers in each bin (e.g. 0~1, 1~2, etc.) have to add up to exactly 100? I am asking because due to rounding some add up to 100.001 and others 99.999, etc. Or am I supposed to declare some kind of special format (e.g. %) for the numbers in each column?</p>
  <p>The plotly options are all relatively new to me, so I could very well be missing something simple. Does anyone have any suggestions? Note that barmode='relative' did not change the outcome.</p>
  <p>Thanks!</p>