|
|
|
|
@@ -0,0 +1,169 @@
|
|
|
|
|
# FILE: trainings_topic_per_center_analysis.py
|
|
|
|
|
# CREATED: 12/24/25
|
|
|
|
|
# AUTHOR: Vincent Allen
|
|
|
|
|
# CONTACT: vincent@vtallen.com valle276@live.kutztown.edu
|
|
|
|
|
# PURPOSE:
|
|
|
|
|
# This file contains plotly figure generating library functions that produce a report for a single center containing info about the topics
|
|
|
|
|
# that appear within trainings for that center.
|
|
|
|
|
# This includes a view of how many events per topic and how many attendees per topic
|
|
|
|
|
|
|
|
|
|
# A percentage graph is provided for each view that simply uses percents out of all events in the center instead of a raw count
|
|
|
|
|
|
|
|
|
|
# third party libraries
|
|
|
|
|
import pandas as pd
|
|
|
|
|
import plotly.graph_objects as go
|
|
|
|
|
import plotly.express as px
|
|
|
|
|
|
|
|
|
|
# python modules
|
|
|
|
|
from enum import Enum
|
|
|
|
|
from typing import Dict
|
|
|
|
|
|
|
|
|
|
# Custom modules
|
|
|
|
|
from section_1_graph_library_module import (
|
|
|
|
|
StatChartVariants
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
from constants_module import NEOSERRA_COLUMNS, OUT_COLUMNS
|
|
|
|
|
|
|
|
|
|
def make_center_topic_analysis(
|
|
|
|
|
trainings_df:pd.DataFrame,
|
|
|
|
|
center_name:str,
|
|
|
|
|
fiscal_year_tag:str="FY25",
|
|
|
|
|
col_neo_center:str=NEOSERRA_COLUMNS.center,
|
|
|
|
|
col_neo_primary_topic:str=NEOSERRA_COLUMNS.primary_training_topic
|
|
|
|
|
) -> Dict[StatChartVariants, go.Figure]:
|
|
|
|
|
"""
|
|
|
|
|
parameters:
|
|
|
|
|
trainings_df:pd.DataFrame - The cleaned trainings data from Neoserra
|
|
|
|
|
center_name:str - The name of the center being processed (For graph titles)
|
|
|
|
|
fiscal_year_tag:str - The fiscal year of the provided data (for graph titles)
|
|
|
|
|
col_neo_center:str - The column at which the center name can be found in the trainings_df
|
|
|
|
|
col_primary_topic:str - The column at which the primary training topic can be found in trainings_df
|
|
|
|
|
|
|
|
|
|
returns: Dict[CenterTopicAnalysisVarients, go.Figure]
|
|
|
|
|
|
|
|
|
|
description:
|
|
|
|
|
Using the cleaned and prepped list of all training events in Neoserra, this function generates a center specific report containing
|
|
|
|
|
bar charts where the x axis is the primary training topics found in that center's events and the y axis is either the number of events
|
|
|
|
|
that had that topic, or the number of attendees who went to events with that topic.
|
|
|
|
|
|
|
|
|
|
Both total count and percentage views are provided.
|
|
|
|
|
|
|
|
|
|
The returned dictionary will have a figure object for each enum key defined in CenterTopicAnalysisVarients
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
collected_graphs = {}
|
|
|
|
|
|
|
|
|
|
center_data = trainings_df[trainings_df[col_neo_center] == center_name]
|
|
|
|
|
|
|
|
|
|
# Attended event counts only
|
|
|
|
|
event_counts_attended = center_data[center_data[NEOSERRA_COLUMNS.attendees_total] >= 1].groupby(NEOSERRA_COLUMNS.primary_training_topic).size().reset_index(name='Event Counts') #pyright:ignore
|
|
|
|
|
attended_count_fig = px.bar(
|
|
|
|
|
event_counts_attended,
|
|
|
|
|
x=col_neo_primary_topic,
|
|
|
|
|
y='Event Counts',
|
|
|
|
|
text='Event Counts',
|
|
|
|
|
title=f'Count of Events for {center_name} by Primary Training Topic Excluding Zero Attendee Events {fiscal_year_tag}',
|
|
|
|
|
width=1250,
|
|
|
|
|
height=600
|
|
|
|
|
)
|
|
|
|
|
total_events = event_counts_attended['Event Counts'].sum()
|
|
|
|
|
attended_count_fig.add_annotation(
|
|
|
|
|
showarrow=False,
|
|
|
|
|
text=f'Sum of Events: {total_events}',
|
|
|
|
|
xref='paper',
|
|
|
|
|
yref='paper',
|
|
|
|
|
x=0,
|
|
|
|
|
y=1.04
|
|
|
|
|
)
|
|
|
|
|
attended_count_fig.update_layout(font_family="Futura",title_font_family="Futura")
|
|
|
|
|
attended_count_fig.update_traces(showlegend=False, marker_color='#197f60')
|
|
|
|
|
collected_graphs[StatChartVariants.TOTAL_ATTENDED] = attended_count_fig
|
|
|
|
|
|
|
|
|
|
# Percent graph
|
|
|
|
|
attended_percent_fig = px.bar(
|
|
|
|
|
event_counts_attended.assign(Percent=lambda x: x['Event Counts'] / x['Event Counts'].sum() * 100),
|
|
|
|
|
x=col_neo_primary_topic,
|
|
|
|
|
y='Percent',
|
|
|
|
|
text='Percent',
|
|
|
|
|
title=f'Percent of Events for {center_name} by Primary Training Topic Excluding Zero Attendee Events {fiscal_year_tag}',
|
|
|
|
|
width=1250,
|
|
|
|
|
height=600
|
|
|
|
|
)
|
|
|
|
|
total_events = event_counts_attended['Event Counts'].sum()
|
|
|
|
|
attended_percent_fig.add_annotation(
|
|
|
|
|
showarrow=False,
|
|
|
|
|
text=f'Sum of Events: {total_events}',
|
|
|
|
|
xref='paper',
|
|
|
|
|
yref='paper',
|
|
|
|
|
x=0,
|
|
|
|
|
y=1.04
|
|
|
|
|
)
|
|
|
|
|
attended_percent_fig.update_layout(
|
|
|
|
|
yaxis_title='Percent of Events',
|
|
|
|
|
font_family="Futura",
|
|
|
|
|
title_font_family="Futura"
|
|
|
|
|
)
|
|
|
|
|
attended_percent_fig.update_traces(
|
|
|
|
|
texttemplate='%{text:.1f}%',
|
|
|
|
|
showlegend=False,
|
|
|
|
|
marker_color='#197f60')
|
|
|
|
|
collected_graphs[StatChartVariants.PERCENT_ATTENDED] = attended_percent_fig
|
|
|
|
|
|
|
|
|
|
# Attendee counts including 0 attendee events
|
|
|
|
|
attendee_counts = center_data.groupby(col_neo_primary_topic)[NEOSERRA_COLUMNS.attendees_total].sum().reset_index(name='Attendee Counts') #pyright:ignore
|
|
|
|
|
total_attendees_fig = px.bar(
|
|
|
|
|
attendee_counts,
|
|
|
|
|
x=col_neo_primary_topic,
|
|
|
|
|
y='Attendee Counts',
|
|
|
|
|
text='Attendee Counts',
|
|
|
|
|
title=f'Count of Attendees for {center_name} by Primary Training Topic {fiscal_year_tag}',
|
|
|
|
|
width=1250,
|
|
|
|
|
height=600
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
total_attendees = attendee_counts['Attendee Counts'].sum()
|
|
|
|
|
total_attendees_fig.add_annotation(
|
|
|
|
|
showarrow=False,
|
|
|
|
|
text=f'Total Attendees: {total_attendees}',
|
|
|
|
|
xref='paper',
|
|
|
|
|
yref='paper',
|
|
|
|
|
x=0,
|
|
|
|
|
y=1.04
|
|
|
|
|
)
|
|
|
|
|
total_attendees_fig.update_layout(font_family="Futura",title_font_family="Futura")
|
|
|
|
|
total_attendees_fig.update_traces(showlegend=False, marker_color='#71bf44')
|
|
|
|
|
collected_graphs[StatChartVariants.TOTAL_COUNT] = total_attendees_fig
|
|
|
|
|
|
|
|
|
|
# Percent graph
|
|
|
|
|
percent_attendees_fig = px.bar(
|
|
|
|
|
attendee_counts.assign(Percent=lambda x: x['Attendee Counts'] / x['Attendee Counts'].sum() * 100),
|
|
|
|
|
x=col_neo_primary_topic,
|
|
|
|
|
y='Percent',
|
|
|
|
|
text='Percent',
|
|
|
|
|
title=f'Percent of Attendees for {center_name} by Primary Training Topic {fiscal_year_tag}',
|
|
|
|
|
width=1250,
|
|
|
|
|
height=600
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
total_attendees = attendee_counts['Attendee Counts'].sum()
|
|
|
|
|
percent_attendees_fig.add_annotation(
|
|
|
|
|
showarrow=False,
|
|
|
|
|
text=f'Total Attendees: {total_attendees}',
|
|
|
|
|
xref='paper',
|
|
|
|
|
yref='paper',
|
|
|
|
|
x=0,
|
|
|
|
|
y=1.04
|
|
|
|
|
)
|
|
|
|
|
percent_attendees_fig.update_layout(
|
|
|
|
|
yaxis_title='Percent of Total Attendees',
|
|
|
|
|
font_family="Futura",
|
|
|
|
|
title_font_family="Futura")
|
|
|
|
|
percent_attendees_fig.update_traces(
|
|
|
|
|
texttemplate='%{text:.1f}%',
|
|
|
|
|
showlegend=False,
|
|
|
|
|
marker_color='#71bf44')
|
|
|
|
|
|
|
|
|
|
collected_graphs[StatChartVariants.TOTAL_PERCENT] = percent_attendees_fig
|
|
|
|
|
|
|
|
|
|
return collected_graphs
|