@@ -224,52 +224,51 @@ Diverging bar charts offer two imperfect options for responses that are neither
224
224
import pandas as pd
225
225
import plotly.graph_objects as go
226
226
227
- data = {
228
- "Category": ["Content Quality", "Value for Money", "Ease of Use", "Customer Support", "Scale Fidelity"],
229
- "Neutral": [10, 15, 18, 15,20],
230
- "Somewhat Agree": [25, 25, 22, 20, 20],
231
- "Strongly Agree": [35, 35, 25, 40, 20],
232
- "Somewhat Disagree": [-20, -15, -20, -10, -20],
233
- "Strongly Disagree": [-10, -10, -15, -15,-20]
234
- }
235
- df = pd.DataFrame(data)
227
+
228
+ df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/refs/heads/master/gss_2002_5_pt_likert.csv')
229
+ #data source details are in this CSV file
230
+ df.rename(columns={'Unnamed: 0':"Category"}, inplace=True)
231
+
232
+
233
+ #achieve the diverging effect by putting a negative sign on the "disagree" answers
234
+ for v in ["Disagree","Strongly Disagree"]:
235
+ df[v]=df[v]*-1
236
236
237
237
fig = go.Figure()
238
- # this color palette conveys meaning: blues for negative, reds for positive, gray for neutral
238
+ # this color palette conveys meaning: blues for negative, reds for positive, gray for Neither Agree nor Disagree
239
239
color_by_category={
240
240
"Strongly Agree":'darkblue',
241
- "Somewhat Agree":'lightblue',
242
- "Somewhat Disagree":'orange',
241
+ "Agree":'lightblue',
242
+ "Disagree":'orange',
243
243
"Strongly Disagree":'red',
244
- "Neutral ":'gray',
244
+ "Neither Agree nor Disagree ":'gray',
245
245
}
246
246
247
+
247
248
# We want the legend to be ordered in the same order that the categories appear, left to right --
248
249
# which is different from the order in which we have to add the traces to the figure.
249
250
# since we need to create the "somewhat" traces before the "strongly" traces to display
250
251
# the segments in the desired order
251
252
252
253
legend_rank_by_category={
253
254
"Strongly Disagree":1,
254
- "Somewhat Disagree":2,
255
- "Somewhat Agree":3,
255
+ "Disagree":2,
256
+ "Agree":3,
256
257
"Strongly Agree":4,
257
- "Neutral ":5
258
+ "Neither Agree nor Disagree ":5
258
259
}
259
260
260
261
# Add bars
261
- for col in df[["Somewhat Disagree","Strongly Disagree","Somewhat Agree","Strongly Agree","Neutral "]]:
262
+ for col in df[["Disagree","Strongly Disagree","Agree","Strongly Agree","Neither Agree nor Disagree "]]:
262
263
fig.add_trace(go.Bar(
263
264
y=df["Category"],
264
265
x=df[col],
265
266
name=col,
266
267
orientation='h',
267
268
marker=dict(color=color_by_category[col]),
268
269
legendrank=legend_rank_by_category[col],
269
- xaxis=f"x{1+(col=="Neutral ")}", # in this context, putting neutral on a secondary x-axis on a different domain
270
+ 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
270
271
# yields results equivalent to subplots with far less code
271
-
272
-
273
272
)
274
273
)
275
274
@@ -278,15 +277,16 @@ for col in df[["Somewhat Disagree","Strongly Disagree","Somewhat Agree","Strongl
278
277
279
278
# Find the maximum width of the bars to the left and right sides of the origin; remember that the width of
280
279
# the plot is the sum of the longest negative bar and the longest positive bar even if they are on separate rows
281
- max_left = min(df[["Somewhat Disagree","Strongly Disagree"]].sum(axis=1))
282
- max_right = max(df[["Somewhat Agree","Strongly Agree"]].sum(axis=1))
280
+ max_left = min(df[["Disagree","Strongly Disagree"]].sum(axis=1))
281
+ max_right = max(df[["Agree","Strongly Agree"]].sum(axis=1))
283
282
284
283
# we are working in percent, but coded the negative reactions as negative numbers; so we need to take the absolute value
285
284
max_width_signed = abs(max_left)+max_right
286
- max_width_neutral = max(df["Neutral "])
285
+ max_width_neither = max(df["Neither Agree nor Disagree "])
287
286
288
287
fig.update_layout(
289
- title="Reactions to the statement, 'The service met your expectations for':",
288
+
289
+ title="Reactions to statements from the 2002 General Social Survey:",
290
290
plot_bgcolor="white",
291
291
barmode='relative', # Allows bars to diverge from the center
292
292
)
@@ -296,12 +296,12 @@ fig.update_xaxes(
296
296
#starting here, we set domain and range to create a shared x-axis scale
297
297
# multiply by .98 to add space between the two columns
298
298
range=[max_left, max_right],
299
- domain=[0, 0.98*(max_width_signed/(max_width_signed+max_width_neutral ))]
299
+ domain=[0, 0.98*(max_width_signed/(max_width_signed+max_width_neither ))]
300
300
)
301
301
fig.update_layout(
302
302
xaxis2=dict(
303
- range=[0, max_width_neutral ],
304
- domain=[(1-.98*(1-max_width_signed/(max_width_signed+max_width_neutral ))), 1.0],
303
+ range=[0, max_width_neither ],
304
+ domain=[(1-.98*(1-max_width_signed/(max_width_signed+max_width_neither ))), 1.0],
305
305
)
306
306
)
307
307
fig.update_legends(
0 commit comments