I was able to eventually produce the plot I wanted and am sharing my solution. I realize this code can be reduced using looping logic, but am sharing this solution as-is for readability. I can’t help but believe there’s a much easier/simpler way to create this plot. If you can think of an easier way, please share!
# Create a dataframe that includes a count of every combination of the three dimensions (evaluator, question, and rating).
evaluators = ['Co-Workers', 'Self']
questions = ['q1', 'q2', 'q3', 'q4', 'q5', 'q6']
ratings = ['Negative', 'Neutral', 'Positive']
from itertools import product
full_df = pd.DataFrame(list(product(evaluators, questions, ratings)), columns=['evaluator', 'question', 'rating'])
def assign_category(x):
if x in ['q1', 'q2']:
return 'A'
elif x in ['q3', 'q4']:
return 'B'
else:
return 'C'
def assign_counts(evaluator, question, rating):
if evaluator == 'Self':
if question in ['q1', 'q5'] and rating == 'Positive':
return 1
elif question in ['q2', 'q3', 'q4', 'q6'] and rating == 'Neutral':
return 1
else:
return 0
elif evaluator == 'Co-Workers':
if question in ['q2', 'q6'] and rating == 'Negative':
return 2
elif question in ['q1', 'q2', 'q6'] and rating == 'Neutral':
return 1
elif question in ['q3', 'q4'] and rating == 'Neutral':
return 4
elif question in ['q2', 'q5'] and rating == 'Positive':
return 1
elif question == 'q1' and rating == 'Positive':
return 3
elif question == 'q5' and rating == 'Neutral':
return 3
else:
return 0
full_df['category'] = full_df['question'].apply(assign_category)
full_df['count'] = full_df.apply(lambda x: assign_counts(x['evaluator'], x['question'], x['rating']), axis=1)
# Make a dataframe for each trace
other_a_negative_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='A') & (full_df.rating=='Negative')]
other_a_neutral_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='A') & (full_df.rating=='Neutral' )]
other_a_positive_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='A') & (full_df.rating=='Positive')]
other_b_negative_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='B') & (full_df.rating=='Negative')]
other_b_neutral_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='B') & (full_df.rating=='Neutral' )]
other_b_positive_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='B') & (full_df.rating=='Positive')]
other_c_negative_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='C') & (full_df.rating=='Negative')]
other_c_neutral_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='C') & (full_df.rating=='Neutral' )]
other_c_positive_df = full_df[(full_df.evaluator=='Co-Workers') & (full_df.category=='C') & (full_df.rating=='Positive')]
self_a_negative_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='A') & (full_df.rating=='Negative')]
self_a_neutral_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='A') & (full_df.rating=='Neutral' )]
self_a_positive_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='A') & (full_df.rating=='Positive')]
self_b_negative_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='B') & (full_df.rating=='Negative')]
self_b_neutral_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='B') & (full_df.rating=='Neutral' )]
self_b_positive_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='B') & (full_df.rating=='Positive')]
self_c_negative_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='C') & (full_df.rating=='Negative')]
self_c_neutral_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='C') & (full_df.rating=='Neutral' )]
self_c_positive_df = full_df[(full_df.evaluator=='Self') & (full_df.category=='C') & (full_df.rating=='Positive')]
fig = make_subplots(rows=3, cols=2, column_widths=[0.9, 0.1], horizontal_spacing=0.02, vertical_spacing=0.075,
shared_xaxes=True, column_titles=["Co-Workers", "Self"], row_titles=["A", "B", "C"])
fig.add_trace(go.Bar(x=other_a_negative_df['count'], y=other_a_negative_df['question'], orientation='h', name='Negative', marker=dict(color='Red' ), legendgroup='Negative'), row=1, col=1)
fig.add_trace(go.Bar(x=other_a_neutral_df['count'] , y=other_a_neutral_df['question'] , orientation='h', name='Neutral' , marker=dict(color='Lime' ), legendgroup='Neutral' ), row=1, col=1)
fig.add_trace(go.Bar(x=other_a_positive_df['count'], y=other_a_positive_df['question'], orientation='h', name='Positive', marker=dict(color='DarkGreen'), legendgroup='Positive'), row=1, col=1)
fig.add_trace(go.Bar(x=other_b_negative_df['count'], y=other_b_negative_df['question'], orientation='h', name='Negative', marker=dict(color='Red' ), legendgroup='Negative', showlegend=False), row=2, col=1)
fig.add_trace(go.Bar(x=other_b_neutral_df['count'] , y=other_b_neutral_df['question'] , orientation='h', name='Neutral' , marker=dict(color='Lime' ), legendgroup='Neutral' , showlegend=False), row=2, col=1)
fig.add_trace(go.Bar(x=other_b_positive_df['count'], y=other_b_positive_df['question'], orientation='h', name='Positive', marker=dict(color='DarkGreen'), legendgroup='Positive', showlegend=False), row=2, col=1)
fig.add_trace(go.Bar(x=other_c_negative_df['count'], y=other_c_negative_df['question'], orientation='h', name='Negative', marker=dict(color='Red' ), legendgroup='Negative', showlegend=False), row=3, col=1)
fig.add_trace(go.Bar(x=other_c_neutral_df['count'] , y=other_c_neutral_df['question'] , orientation='h', name='Neutral' , marker=dict(color='Lime' ), legendgroup='Neutral' , showlegend=False), row=3, col=1)
fig.add_trace(go.Bar(x=other_c_positive_df['count'], y=other_c_positive_df['question'], orientation='h', name='Positive', marker=dict(color='DarkGreen'), legendgroup='Positive', showlegend=False), row=3, col=1)
fig.add_trace(go.Bar(x=self_a_negative_df['count'], y=self_a_negative_df['question'], orientation='h', name='Negative', marker=dict(color='Red' ), legendgroup='Negative', showlegend=False), row=1, col=2)
fig.add_trace(go.Bar(x=self_a_neutral_df['count'] , y=self_a_neutral_df['question'] , orientation='h', name='Neutral' , marker=dict(color='Lime' ), legendgroup='Neutral' , showlegend=False), row=1, col=2)
fig.add_trace(go.Bar(x=self_a_positive_df['count'], y=self_a_positive_df['question'], orientation='h', name='Positive', marker=dict(color='DarkGreen'), legendgroup='Positive', showlegend=False), row=1, col=2)
fig.add_trace(go.Bar(x=self_b_negative_df['count'], y=self_b_negative_df['question'], orientation='h', name='Negative', marker=dict(color='Red' ), legendgroup='Negative', showlegend=False), row=2, col=2)
fig.add_trace(go.Bar(x=self_b_neutral_df['count'] , y=self_b_neutral_df['question'] , orientation='h', name='Neutral' , marker=dict(color='Lime' ), legendgroup='Neutral' , showlegend=False), row=2, col=2)
fig.add_trace(go.Bar(x=self_b_positive_df['count'], y=self_b_positive_df['question'], orientation='h', name='Positive', marker=dict(color='DarkGreen'), legendgroup='Positive', showlegend=False), row=2, col=2)
fig.add_trace(go.Bar(x=self_c_negative_df['count'], y=self_c_negative_df['question'], orientation='h', name='Negative', marker=dict(color='Red' ), legendgroup='Negative', showlegend=False), row=3, col=2)
fig.add_trace(go.Bar(x=self_c_neutral_df['count'] , y=self_c_neutral_df['question'] , orientation='h', name='Neutral' , marker=dict(color='Lime' ), legendgroup='Neutral' , showlegend=False), row=3, col=2)
fig.add_trace(go.Bar(x=self_c_positive_df['count'], y=self_c_positive_df['question'], orientation='h', name='Positive', marker=dict(color='DarkGreen'), legendgroup='Positive', showlegend=False), row=3, col=2)
fig.update_layout(barmode='stack', title="Performance Ratings - Plotly Graph Objects Bar Plot", hovermode=False,
legend=dict(orientation='h', xanchor='center', yanchor='bottom', x=0.5, y=-0.3, title=''),
width=900, height=450, autosize=False)
fig.update_yaxes(categoryorder='category descending')
fig.update_xaxes(tick0=0, dtick=1, range=[0,4.125], col=1)
fig.update_xaxes(showticklabels=False, range=[0,1.25], col=2)
fig.update_yaxes(showticklabels=False, col=2)
fig['layout']['xaxis5']['title']['text']='Count of Responses'
fig['layout']['xaxis6']['title']['text']=''
fig.show()