import pandas as pd import plotly.express as px import plotly.graph_objects as go from .basePlotlyAnalysis import BasePlotlyAnalysis from flask import current_app, url_for class PlotlyActivityHeatmap(BasePlotlyAnalysis): """ Class for analyzing user activity trends over multiple days and generating an interactive heatmap. Attributes: name (str): The name of the analysis. description (str): A brief description of the analysis. plot_filename (str): The filename for the output plot. note (str): Additional notes for the analysis. """ name = "Activity Heatmap (Interactive)" description = "Displays user activity trends over multiple days using an interactive heatmap." plot_filename = "activity_heatmap.html" note = "" def transform_data(self, df: pd.DataFrame) -> pd.DataFrame: """ Transform data for the heatmap. Parameters: df (pd.DataFrame): The input DataFrame containing user activity data. Returns: pd.DataFrame: The transformed DataFrame with activity counts by hour. """ df['hour'] = df['timestamp'].dt.hour active_counts = df[df['was_active']].pivot_table( index='name', columns='hour', values='was_active', aggfunc='sum', fill_value=0 ).reset_index() # Ensure all hours are represented all_hours = pd.DataFrame({'hour': range(24)}) active_counts = active_counts.melt(id_vars='name', var_name='hour', value_name='activity_count') active_counts = active_counts.merge(all_hours, on='hour', how='right').fillna(0) active_counts['hour'] = active_counts['hour'].astype(int) # Ensure hour is treated as numeric return active_counts def plot_data(self, df: pd.DataFrame): """ Generate heatmap plot. Parameters: df (pd.DataFrame): The transformed DataFrame containing activity counts by hour. """ df = df.pivot(index='name', columns='hour', values='activity_count').fillna(0) # Create a Plotly heatmap self.fig = go.Figure(data=go.Heatmap( z=df.values, x=df.columns, y=df.index, colorscale='Viridis', colorbar=dict(title='Count of was_active == True') )) # Update layout self.fig.update_layout( title='User Activity Heatmap', xaxis_title='Hour of Day', yaxis_title='User ID', xaxis=dict(tickmode='linear', dtick=1, range=[0, 23]), # Ensure x-axis covers all hours template='plotly_white' ) self.fig.update_traces( hovertemplate="
".join([ "Hour: %{x}", "Name: %{y}", "Activity: %{z}", ]) )