From fbc94a2dff961e72873993632c3853aff2069098 Mon Sep 17 00:00:00 2001 From: SimaRaha Date: Wed, 1 Jan 2025 13:11:34 -0500 Subject: [PATCH 1/4] Added plotly-universities-1.ipynb for visualization updates --- plotly-universities-1.ipynb | 1360 +++++++++++++++++++++++++++++++++++ 1 file changed, 1360 insertions(+) create mode 100644 plotly-universities-1.ipynb diff --git a/plotly-universities-1.ipynb b/plotly-universities-1.ipynb new file mode 100644 index 0000000000..dbbaddb98f --- /dev/null +++ b/plotly-universities-1.ipynb @@ -0,0 +1,1360 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hoverinfo": "text", + "marker": { + "color": 0, + "size": 27, + "symbol": "square" + }, + "mode": "markers", + "name": "Haverford College", + "text": [ + "Haverford College: 1421" + ], + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 1.05 + ] + }, + { + "mode": "text", + "showlegend": false, + "text": [ + "1421" + ], + "textfont": { + "color": "black", + "size": 14 + }, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 11 + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": 1, + "size": 27, + "symbol": "square" + }, + "mode": "markers", + "name": "University of Mary Washington", + "text": [ + "University of Mary Washington: 3611", + "University of Mary Washington: 3611", + "University of Mary Washington: 3611", + "University of Mary Washington: 3611" + ], + "type": "scatter", + "x": [ + 2.005, + 2.005, + 2.005, + 2.005 + ], + "y": [ + 1.05, + 2.1, + 3.15, + 4.2 + ] + }, + { + "mode": "text", + "showlegend": false, + "text": [ + "3611" + ], + "textfont": { + "color": "black", + "size": 14 + }, + "type": "scatter", + "x": [ + 2.005 + ], + "y": [ + 11 + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": 2, + "size": 27, + "symbol": "square" + }, + "mode": "markers", + "name": "Brown University", + "text": [ + "Brown University: 7226", + "Brown University: 7226", + "Brown University: 7226", + "Brown University: 7226", + "Brown University: 7226", + "Brown University: 7226", + "Brown University: 7226" + ], + "type": "scatter", + "x": [ + 3.01, + 3.01, + 3.01, + 3.01, + 3.01, + 3.01, + 3.01 + ], + "y": [ + 1.05, + 2.1, + 3.15, + 4.2, + 5.25, + 6.3, + 7.35 + ] + }, + { + "mode": "text", + "showlegend": false, + "text": [ + "7226" + ], + "textfont": { + "color": "black", + "size": 14 + }, + "type": "scatter", + "x": [ + 3.01 + ], + "y": [ + 11 + ] + }, + { + "hoverinfo": "text", + "marker": { + "color": 3, + "size": 27, + "symbol": "square" + }, + "mode": "markers", + "name": "Arizona State University", + "text": [ + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174", + "Arizona State University: 65174" + ], + "type": "scatter", + "x": [ + 4.015, + 4.015, + 4.015, + 4.015, + 4.015, + 4.015, + 4.015, + 4.015, + 4.015, + 4.015, + 5.015, + 5.015, + 5.015, + 5.015, + 5.015, + 5.015, + 5.015, + 5.015, + 5.015, + 5.015, + 6.015, + 6.015, + 6.015, + 6.015, + 6.015, + 6.015, + 6.015, + 6.015, + 6.015, + 6.015, + 7.015, + 7.015, + 7.015, + 7.015, + 7.015, + 7.015, + 7.015, + 7.015, + 7.015, + 7.015, + 8.015, + 8.015, + 8.015, + 8.015, + 8.015, + 8.015, + 8.015, + 8.015, + 8.015, + 8.015, + 9.015, + 9.015, + 9.015, + 9.015, + 9.015, + 9.015, + 9.015, + 9.015, + 9.015, + 9.015, + 10.015, + 10.015, + 10.015, + 10.015, + 10.015 + ], + "y": [ + 1.05, + 2.1, + 3.15, + 4.2, + 5.25, + 6.3, + 7.35, + 8.4, + 9.45, + 10.5, + 1.05, + 2.1, + 3.15, + 4.2, + 5.25, + 6.3, + 7.35, + 8.4, + 9.45, + 10.5, + 1.05, + 2.1, + 3.15, + 4.2, + 5.25, + 6.3, + 7.35, + 8.4, + 9.45, + 10.5, + 1.05, + 2.1, + 3.15, + 4.2, + 5.25, + 6.3, + 7.35, + 8.4, + 9.45, + 10.5, + 1.05, + 2.1, + 3.15, + 4.2, + 5.25, + 6.3, + 7.35, + 8.4, + 9.45, + 10.5, + 1.05, + 2.1, + 3.15, + 4.2, + 5.25, + 6.3, + 7.35, + 8.4, + 9.45, + 10.5, + 1.05, + 2.1, + 3.15, + 4.2, + 5.25 + ] + }, + { + "mode": "text", + "showlegend": false, + "text": [ + "65174" + ], + "textfont": { + "color": "black", + "size": 14 + }, + "type": "scatter", + "x": [ + 7.015 + ], + "y": [ + 11 + ] + } + ], + "layout": { + "height": 600, + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Undergraduate Enrollment at Participating Schools" + }, + "width": 1000, + "xaxis": { + "showgrid": false, + "tickangle": -45, + "ticktext": [ + "Haverford College", + "University of Mary Washington", + "Brown University", + "Arizona State University" + ], + "tickvals": [ + 1, + 2.005, + 3.01, + 7.015 + ], + "title": { + "text": "Categories" + } + }, + "yaxis": { + "showgrid": false, + "title": { + "text": "Units (1 icon = 1000)" + }, + "zeroline": false + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import plotly.graph_objects as go\n", + "import pandas as pd\n", + "\n", + "def pictogram_bar(data, title, icon_size, max_height=10, units_per_icon=1, column_spacing=0.005,icon_spacing=0.005):\n", + " \n", + " fig = go.Figure()\n", + " x_start = 1\n", + " tick_locations = []\n", + "\n", + " for i, (category, value) in enumerate(data.items()):\n", + " icon_count = round(value / units_per_icon)\n", + " num_columns = -(-icon_count // max_height) # Ceiling division\n", + "\n", + " x_coordinates, y_coordinates = [], []\n", + " for col in range(num_columns):\n", + " column_icons = min(max_height, icon_count - col * max_height)\n", + " x_coordinates.extend([x_start + col] * column_icons)\n", + " # y_coordinates.extend(range(1, column_icons + 1))\n", + " y_coordinates.extend([y + icon_spacing * y for y in range(1, column_icons + 1)])\n", + "\n", + "\n", + " # Add scatter plot for the category\n", + " fig.add_trace(go.Scatter(\n", + " x=x_coordinates,\n", + " y=y_coordinates,\n", + " mode='markers',\n", + " marker=dict(size=icon_size, symbol=\"square\", color= i),\n", + " name=category,\n", + " hoverinfo=\"text\",\n", + " text=[f\"{category}: {value}\" for _ in range(len(x_coordinates))]\n", + " ))\n", + " \n", + "\n", + " # Add value annotations above the section: new line of code \n", + " fig.add_trace(go.Scatter(\n", + " x=[x_start + (num_columns - 1) / 2],\n", + " y=[max_height + 1],\n", + " mode=\"text\",\n", + " text=[f\"{value}\"],\n", + " textfont=dict(size=14, color=\"black\"),\n", + " showlegend=False\n", + " ))\n", + "\n", + " # Track tick locations\n", + " tick_locations.append(x_start + (num_columns - 1) / 2)\n", + " x_start += num_columns + column_spacing\n", + "\n", + " # Update layout\n", + " fig.update_layout(\n", + " title=title,\n", + " xaxis=dict(\n", + " tickvals=tick_locations,\n", + " ticktext=list(data.keys()),\n", + " tickangle=-45,\n", + " showgrid=False,\n", + " title=\"Categories\"\n", + " ),\n", + " yaxis=dict(\n", + " title=f\"Units (1 icon = {units_per_icon})\",\n", + " showgrid=False,\n", + " zeroline=False,\n", + " ),\n", + " showlegend=False,\n", + " height=600,\n", + " width=(len(data) * 200 + 200) # Done adjused width based on number of categories\n", + " )\n", + "\n", + " fig.show()\n", + "\n", + "\n", + "# done as pd \n", + "df = pd.DataFrame({\n", + " 'School': [\"Haverford College\", \"University of Mary Washington\", \"Brown University\", \"Arizona State University\"],\n", + " 'Enrollment': [1421, 3611, 7226, 65174]\n", + "})\n", + "\n", + "pictogram_bar(\n", + " data={row['School']: row['Enrollment'] for _, row in df.iterrows()},\n", + " title=\"Undergraduate Enrollment at Participating Schools\",\n", + " units_per_icon=1000,\n", + " icon_size=27,\n", + " icon_spacing=0.05\n", + ")\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "3.11.9", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From f386c0baeaa1cf40bed3bad4158254b69de41bbf Mon Sep 17 00:00:00 2001 From: Rob Letzler <22990670+rl-utility-man@users.noreply.github.com> Date: Thu, 6 Feb 2025 00:11:12 -0500 Subject: [PATCH 2/4] butterfly with neutral column --- doc/python/horizontal-bar-charts.md | 105 +++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 2 deletions(-) diff --git a/doc/python/horizontal-bar-charts.md b/doc/python/horizontal-bar-charts.md index 25aa9d4f7d..f68a34989d 100644 --- a/doc/python/horizontal-bar-charts.md +++ b/doc/python/horizontal-bar-charts.md @@ -214,6 +214,107 @@ for yd, xd in zip(y_data, x_data): fig.update_layout(annotations=annotations) +fig.show() +``` +### Diverging Bar (or Butterfly) Chart with Neutral Column + +Diverging bar charts offer two imperfect options for responses that are neither positive nor negative: omit them, leaving them implicit when the categories add to 100%, as we did above or put them in a separate column, as we do in this example. Jonathan Schwabish discusses this on page 92-97 of _Better Data Visualizations_. + +``` +import pandas as pd +import plotly.graph_objects as go + +data = { + "Category": ["Content Quality", "Value for Money", "Ease of Use", "Customer Support", "Scale Fidelity"], + "Neutral": [10, 15, 18, 15,20], + "Somewhat Agree": [25, 25, 22, 20, 20], + "Strongly Agree": [35, 35, 25, 40, 20], + "Somewhat Disagree": [-20, -15, -20, -10, -20], + "Strongly Disagree": [-10, -10, -15, -15,-20] +} +df = pd.DataFrame(data) + +fig = go.Figure() +# this color palette conveys meaning: blues for negative, reds for positive, gray for neutral +color_by_category={ + "Strongly Agree":'darkblue', + "Somewhat Agree":'lightblue', + "Somewhat Disagree":'orange', + "Strongly Disagree":'red', + "Neutral":'gray', +} + +# We want the legend to be ordered in the same order that the categories appear, left to right -- +# which is different from the order in which we have to add the traces to the figure. +# since we need to create the "somewhat" traces before the "strongly" traces to display +# the segments in the desired order + +legend_rank_by_category={ + "Strongly Disagree":1, + "Somewhat Disagree":2, + "Somewhat Agree":3, + "Strongly Agree":4, + "Neutral":5 +} + +# Add bars +for col in df[["Somewhat Disagree","Strongly Disagree","Somewhat Agree","Strongly Agree","Neutral"]]: + fig.add_trace(go.Bar( + y=df["Category"], + x=df[col], + name=col, + orientation='h', + marker=dict(color=color_by_category[col]), + legendrank=legend_rank_by_category[col], + xaxis=f"x{1+(col=="Neutral")}", # in this context, putting neutral on a secondary x-axis on a different domain + # yields results equivalent to subplots with far less code + + + ) +) + +# make calculations to split the plot into two columns with a shared x axis scale +# by setting the domain and range of the x axes appropriately + +# Find the maximum width of the bars to the left and right sides of the origin; remember that the width of +# the plot is the sum of the longest negative bar and the longest positive bar even if they are on separate rows +max_left = min(df[["Somewhat Disagree","Strongly Disagree"]].sum(axis=1)) +max_right = max(df[["Somewhat Agree","Strongly Agree"]].sum(axis=1)) + +# we are working in percent, but coded the negative reactions as negative numbers; so we need to take the absolute value +max_width_signed = abs(max_left)+max_right +max_width_neutral = max(df["Neutral"]) + +fig.update_layout( + title="Reactions to the statement, 'The service met your expectations for':", + plot_bgcolor="white", + barmode='relative', # Allows bars to diverge from the center + ) +fig.update_xaxes( + zeroline=True, #the zero line distinguishes between positive and negative segments + zerolinecolor="black", + #starting here, we set domain and range to create a shared x-axis scale + # multiply by .98 to add space between the two columns + range=[max_left, max_right], + domain=[0, 0.98*(max_width_signed/(max_width_signed+max_width_neutral))] +) +fig.update_layout( + xaxis2=dict( + range=[0, max_width_neutral], + domain=[(1-.98*(1-max_width_signed/(max_width_signed+max_width_neutral))), 1.0], + ) +) +fig.update_legends( + orientation="h", # a horizontal legend matches the horizontal bars + yref="container", + yanchor="bottom", + y=0.02, + xanchor="center", + x=0.5 +) + +fig.update_yaxes(title="") + fig.show() ``` @@ -260,7 +361,7 @@ fig.append_trace(go.Scatter( ), 1, 2) fig.update_layout( - title='Household savings & net worth for eight OECD countries', + title=dict(text='Household savings & net worth for eight OECD countries'), yaxis=dict( showgrid=False, showline=False, @@ -335,4 +436,4 @@ fig.show() ### Reference -See more examples of bar charts and styling options [here](https://plotly.com/python/bar-charts/).
See https://plotly.com/python/reference/bar/ for more information and chart attribute options! \ No newline at end of file +See more examples of bar charts and styling options [here](https://plotly.com/python/bar-charts/).
See https://plotly.com/python/reference/bar/ for more information and chart attribute options! From 911b99348397d75e73ce018034efd186af69f49b Mon Sep 17 00:00:00 2001 From: Rob Letzler <22990670+rl-utility-man@users.noreply.github.com> Date: Thu, 6 Feb 2025 00:12:27 -0500 Subject: [PATCH 3/4] Delete scratchwork file --- plotly-universities-1.ipynb | 1360 ----------------------------------- 1 file changed, 1360 deletions(-) delete mode 100644 plotly-universities-1.ipynb diff --git a/plotly-universities-1.ipynb b/plotly-universities-1.ipynb deleted file mode 100644 index dbbaddb98f..0000000000 --- a/plotly-universities-1.ipynb +++ /dev/null @@ -1,1360 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ - { - "hoverinfo": "text", - "marker": { - "color": 0, - "size": 27, - "symbol": "square" - }, - "mode": "markers", - "name": "Haverford College", - "text": [ - "Haverford College: 1421" - ], - "type": "scatter", - "x": [ - 1 - ], - "y": [ - 1.05 - ] - }, - { - "mode": "text", - "showlegend": false, - "text": [ - "1421" - ], - "textfont": { - "color": "black", - "size": 14 - }, - "type": "scatter", - "x": [ - 1 - ], - "y": [ - 11 - ] - }, - { - "hoverinfo": "text", - "marker": { - "color": 1, - "size": 27, - "symbol": "square" - }, - "mode": "markers", - "name": "University of Mary Washington", - "text": [ - "University of Mary Washington: 3611", - "University of Mary Washington: 3611", - "University of Mary Washington: 3611", - "University of Mary Washington: 3611" - ], - "type": "scatter", - "x": [ - 2.005, - 2.005, - 2.005, - 2.005 - ], - "y": [ - 1.05, - 2.1, - 3.15, - 4.2 - ] - }, - { - "mode": "text", - "showlegend": false, - "text": [ - "3611" - ], - "textfont": { - "color": "black", - "size": 14 - }, - "type": "scatter", - "x": [ - 2.005 - ], - "y": [ - 11 - ] - }, - { - "hoverinfo": "text", - "marker": { - "color": 2, - "size": 27, - "symbol": "square" - }, - "mode": "markers", - "name": "Brown University", - "text": [ - "Brown University: 7226", - "Brown University: 7226", - "Brown University: 7226", - "Brown University: 7226", - "Brown University: 7226", - "Brown University: 7226", - "Brown University: 7226" - ], - "type": "scatter", - "x": [ - 3.01, - 3.01, - 3.01, - 3.01, - 3.01, - 3.01, - 3.01 - ], - "y": [ - 1.05, - 2.1, - 3.15, - 4.2, - 5.25, - 6.3, - 7.35 - ] - }, - { - "mode": "text", - "showlegend": false, - "text": [ - "7226" - ], - "textfont": { - "color": "black", - "size": 14 - }, - "type": "scatter", - "x": [ - 3.01 - ], - "y": [ - 11 - ] - }, - { - "hoverinfo": "text", - "marker": { - "color": 3, - "size": 27, - "symbol": "square" - }, - "mode": "markers", - "name": "Arizona State University", - "text": [ - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174", - "Arizona State University: 65174" - ], - "type": "scatter", - "x": [ - 4.015, - 4.015, - 4.015, - 4.015, - 4.015, - 4.015, - 4.015, - 4.015, - 4.015, - 4.015, - 5.015, - 5.015, - 5.015, - 5.015, - 5.015, - 5.015, - 5.015, - 5.015, - 5.015, - 5.015, - 6.015, - 6.015, - 6.015, - 6.015, - 6.015, - 6.015, - 6.015, - 6.015, - 6.015, - 6.015, - 7.015, - 7.015, - 7.015, - 7.015, - 7.015, - 7.015, - 7.015, - 7.015, - 7.015, - 7.015, - 8.015, - 8.015, - 8.015, - 8.015, - 8.015, - 8.015, - 8.015, - 8.015, - 8.015, - 8.015, - 9.015, - 9.015, - 9.015, - 9.015, - 9.015, - 9.015, - 9.015, - 9.015, - 9.015, - 9.015, - 10.015, - 10.015, - 10.015, - 10.015, - 10.015 - ], - "y": [ - 1.05, - 2.1, - 3.15, - 4.2, - 5.25, - 6.3, - 7.35, - 8.4, - 9.45, - 10.5, - 1.05, - 2.1, - 3.15, - 4.2, - 5.25, - 6.3, - 7.35, - 8.4, - 9.45, - 10.5, - 1.05, - 2.1, - 3.15, - 4.2, - 5.25, - 6.3, - 7.35, - 8.4, - 9.45, - 10.5, - 1.05, - 2.1, - 3.15, - 4.2, - 5.25, - 6.3, - 7.35, - 8.4, - 9.45, - 10.5, - 1.05, - 2.1, - 3.15, - 4.2, - 5.25, - 6.3, - 7.35, - 8.4, - 9.45, - 10.5, - 1.05, - 2.1, - 3.15, - 4.2, - 5.25, - 6.3, - 7.35, - 8.4, - 9.45, - 10.5, - 1.05, - 2.1, - 3.15, - 4.2, - 5.25 - ] - }, - { - "mode": "text", - "showlegend": false, - "text": [ - "65174" - ], - "textfont": { - "color": "black", - "size": 14 - }, - "type": "scatter", - "x": [ - 7.015 - ], - "y": [ - 11 - ] - } - ], - "layout": { - "height": 600, - "showlegend": false, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "#2a3f5f" - }, - "error_y": { - "color": "#2a3f5f" - }, - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "baxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "#EBF0F8" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "#C8D4E3" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowcolor": "#2a3f5f", - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "colorscale": { - "diverging": [ - [ - 0, - "#8e0152" - ], - [ - 0.1, - "#c51b7d" - ], - [ - 0.2, - "#de77ae" - ], - [ - 0.3, - "#f1b6da" - ], - [ - 0.4, - "#fde0ef" - ], - [ - 0.5, - "#f7f7f7" - ], - [ - 0.6, - "#e6f5d0" - ], - [ - 0.7, - "#b8e186" - ], - [ - 0.8, - "#7fbc41" - ], - [ - 0.9, - "#4d9221" - ], - [ - 1, - "#276419" - ] - ], - "sequential": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "sequentialminus": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ] - }, - "colorway": [ - "#636efa", - "#EF553B", - "#00cc96", - "#ab63fa", - "#FFA15A", - "#19d3f3", - "#FF6692", - "#B6E880", - "#FF97FF", - "#FECB52" - ], - "font": { - "color": "#2a3f5f" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "#E5ECF6", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "mapbox": { - "style": "light" - }, - "paper_bgcolor": "white", - "plot_bgcolor": "#E5ECF6", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "line": { - "color": "#2a3f5f" - } - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "title": { - "x": 0.05 - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - } - } - }, - "title": { - "text": "Undergraduate Enrollment at Participating Schools" - }, - "width": 1000, - "xaxis": { - "showgrid": false, - "tickangle": -45, - "ticktext": [ - "Haverford College", - "University of Mary Washington", - "Brown University", - "Arizona State University" - ], - "tickvals": [ - 1, - 2.005, - 3.01, - 7.015 - ], - "title": { - "text": "Categories" - } - }, - "yaxis": { - "showgrid": false, - "title": { - "text": "Units (1 icon = 1000)" - }, - "zeroline": false - } - } - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import plotly.graph_objects as go\n", - "import pandas as pd\n", - "\n", - "def pictogram_bar(data, title, icon_size, max_height=10, units_per_icon=1, column_spacing=0.005,icon_spacing=0.005):\n", - " \n", - " fig = go.Figure()\n", - " x_start = 1\n", - " tick_locations = []\n", - "\n", - " for i, (category, value) in enumerate(data.items()):\n", - " icon_count = round(value / units_per_icon)\n", - " num_columns = -(-icon_count // max_height) # Ceiling division\n", - "\n", - " x_coordinates, y_coordinates = [], []\n", - " for col in range(num_columns):\n", - " column_icons = min(max_height, icon_count - col * max_height)\n", - " x_coordinates.extend([x_start + col] * column_icons)\n", - " # y_coordinates.extend(range(1, column_icons + 1))\n", - " y_coordinates.extend([y + icon_spacing * y for y in range(1, column_icons + 1)])\n", - "\n", - "\n", - " # Add scatter plot for the category\n", - " fig.add_trace(go.Scatter(\n", - " x=x_coordinates,\n", - " y=y_coordinates,\n", - " mode='markers',\n", - " marker=dict(size=icon_size, symbol=\"square\", color= i),\n", - " name=category,\n", - " hoverinfo=\"text\",\n", - " text=[f\"{category}: {value}\" for _ in range(len(x_coordinates))]\n", - " ))\n", - " \n", - "\n", - " # Add value annotations above the section: new line of code \n", - " fig.add_trace(go.Scatter(\n", - " x=[x_start + (num_columns - 1) / 2],\n", - " y=[max_height + 1],\n", - " mode=\"text\",\n", - " text=[f\"{value}\"],\n", - " textfont=dict(size=14, color=\"black\"),\n", - " showlegend=False\n", - " ))\n", - "\n", - " # Track tick locations\n", - " tick_locations.append(x_start + (num_columns - 1) / 2)\n", - " x_start += num_columns + column_spacing\n", - "\n", - " # Update layout\n", - " fig.update_layout(\n", - " title=title,\n", - " xaxis=dict(\n", - " tickvals=tick_locations,\n", - " ticktext=list(data.keys()),\n", - " tickangle=-45,\n", - " showgrid=False,\n", - " title=\"Categories\"\n", - " ),\n", - " yaxis=dict(\n", - " title=f\"Units (1 icon = {units_per_icon})\",\n", - " showgrid=False,\n", - " zeroline=False,\n", - " ),\n", - " showlegend=False,\n", - " height=600,\n", - " width=(len(data) * 200 + 200) # Done adjused width based on number of categories\n", - " )\n", - "\n", - " fig.show()\n", - "\n", - "\n", - "# done as pd \n", - "df = pd.DataFrame({\n", - " 'School': [\"Haverford College\", \"University of Mary Washington\", \"Brown University\", \"Arizona State University\"],\n", - " 'Enrollment': [1421, 3611, 7226, 65174]\n", - "})\n", - "\n", - "pictogram_bar(\n", - " data={row['School']: row['Enrollment'] for _, row in df.iterrows()},\n", - " title=\"Undergraduate Enrollment at Participating Schools\",\n", - " units_per_icon=1000,\n", - " icon_size=27,\n", - " icon_spacing=0.05\n", - ")\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "3.11.9", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 40cd4c8e22d895b842edae8d30f3d4fef810135e Mon Sep 17 00:00:00 2001 From: Rob Letzler <22990670+rl-utility-man@users.noreply.github.com> Date: Sun, 16 Mar 2025 14:52:57 -0400 Subject: [PATCH 4/4] replaced hard coded data with a read_csv from github --- doc/python/horizontal-bar-charts.md | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/doc/python/horizontal-bar-charts.md b/doc/python/horizontal-bar-charts.md index f68a34989d..52cd62f0ae 100644 --- a/doc/python/horizontal-bar-charts.md +++ b/doc/python/horizontal-bar-charts.md @@ -224,26 +224,27 @@ Diverging bar charts offer two imperfect options for responses that are neither import pandas as pd import plotly.graph_objects as go -data = { - "Category": ["Content Quality", "Value for Money", "Ease of Use", "Customer Support", "Scale Fidelity"], - "Neutral": [10, 15, 18, 15,20], - "Somewhat Agree": [25, 25, 22, 20, 20], - "Strongly Agree": [35, 35, 25, 40, 20], - "Somewhat Disagree": [-20, -15, -20, -10, -20], - "Strongly Disagree": [-10, -10, -15, -15,-20] -} -df = pd.DataFrame(data) + +df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/refs/heads/master/gss_2002_5_pt_likert.csv') +#data source details are in this CSV file +df.rename(columns={'Unnamed: 0':"Category"}, inplace=True) + + +#achieve the diverging effect by putting a negative sign on the "disagree" answers +for v in ["Disagree","Strongly Disagree"]: + df[v]=df[v]*-1 fig = go.Figure() -# this color palette conveys meaning: blues for negative, reds for positive, gray for neutral +# this color palette conveys meaning: blues for negative, reds for positive, gray for Neither Agree nor Disagree color_by_category={ "Strongly Agree":'darkblue', - "Somewhat Agree":'lightblue', - "Somewhat Disagree":'orange', + "Agree":'lightblue', + "Disagree":'orange', "Strongly Disagree":'red', - "Neutral":'gray', + "Neither Agree nor Disagree":'gray', } + # We want the legend to be ordered in the same order that the categories appear, left to right -- # which is different from the order in which we have to add the traces to the figure. # since we need to create the "somewhat" traces before the "strongly" traces to display @@ -251,14 +252,14 @@ color_by_category={ legend_rank_by_category={ "Strongly Disagree":1, - "Somewhat Disagree":2, - "Somewhat Agree":3, + "Disagree":2, + "Agree":3, "Strongly Agree":4, - "Neutral":5 + "Neither Agree nor Disagree":5 } # Add bars -for col in df[["Somewhat Disagree","Strongly Disagree","Somewhat Agree","Strongly Agree","Neutral"]]: +for col in df[["Disagree","Strongly Disagree","Agree","Strongly Agree","Neither Agree nor Disagree"]]: fig.add_trace(go.Bar( y=df["Category"], x=df[col], @@ -266,10 +267,8 @@ for col in df[["Somewhat Disagree","Strongly Disagree","Somewhat Agree","Strongl orientation='h', marker=dict(color=color_by_category[col]), legendrank=legend_rank_by_category[col], - xaxis=f"x{1+(col=="Neutral")}", # in this context, putting neutral on a secondary x-axis on a different domain + xaxis=f"x{1+(col=="Neither Agree nor Disagree")}", # in this context, putting "Neither Agree nor Disagree" on a secondary x-axis on a different domain # yields results equivalent to subplots with far less code - - ) ) @@ -278,15 +277,16 @@ for col in df[["Somewhat Disagree","Strongly Disagree","Somewhat Agree","Strongl # Find the maximum width of the bars to the left and right sides of the origin; remember that the width of # the plot is the sum of the longest negative bar and the longest positive bar even if they are on separate rows -max_left = min(df[["Somewhat Disagree","Strongly Disagree"]].sum(axis=1)) -max_right = max(df[["Somewhat Agree","Strongly Agree"]].sum(axis=1)) +max_left = min(df[["Disagree","Strongly Disagree"]].sum(axis=1)) +max_right = max(df[["Agree","Strongly Agree"]].sum(axis=1)) # we are working in percent, but coded the negative reactions as negative numbers; so we need to take the absolute value max_width_signed = abs(max_left)+max_right -max_width_neutral = max(df["Neutral"]) +max_width_neither = max(df["Neither Agree nor Disagree"]) fig.update_layout( - title="Reactions to the statement, 'The service met your expectations for':", + + title="Reactions to statements from the 2002 General Social Survey:", plot_bgcolor="white", barmode='relative', # Allows bars to diverge from the center ) @@ -296,12 +296,12 @@ fig.update_xaxes( #starting here, we set domain and range to create a shared x-axis scale # multiply by .98 to add space between the two columns range=[max_left, max_right], - domain=[0, 0.98*(max_width_signed/(max_width_signed+max_width_neutral))] + domain=[0, 0.98*(max_width_signed/(max_width_signed+max_width_neither))] ) fig.update_layout( xaxis2=dict( - range=[0, max_width_neutral], - domain=[(1-.98*(1-max_width_signed/(max_width_signed+max_width_neutral))), 1.0], + range=[0, max_width_neither], + domain=[(1-.98*(1-max_width_signed/(max_width_signed+max_width_neither))), 1.0], ) ) fig.update_legends(