-
Notifications
You must be signed in to change notification settings - Fork 3
Graph integration #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
12817e8
3aa5abc
eab04b2
81d1275
54a4d96
da2c1c1
a9496f6
fcd37ca
3d0c4f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,59 +1,63 @@ | ||
| from dash import html | ||
| # pages/pgp.py | ||
|
|
||
| from dash import html, dcc | ||
| from utils.pgpxd4g_graphs import get_figures | ||
|
|
||
| def make_layout(): | ||
|
|
||
| trend, lang, source, themes = get_figures() | ||
|
|
||
| def create_layout(): | ||
| return html.Div( | ||
| style={ | ||
| "backgroundColor": "#FFFFFF", | ||
| "backgroundColor": "#F4F6F8", | ||
| "padding": "20px", | ||
| "fontFamily": "Arial", | ||
| "padding": "20px" | ||
| }, | ||
|
|
||
| children=[ | ||
|
|
||
| # HEADER | ||
| html.Div( | ||
| children=[ | ||
| html.H1( | ||
| "PGP Dashboard", | ||
| style={ | ||
| "color": "white", | ||
| "textAlign": "center", | ||
| "margin": "0" | ||
| } | ||
| ) | ||
| ], | ||
| "PGP Dashboard", | ||
| style={ | ||
| "backgroundColor": "#00669B", | ||
| "backgroundColor": "#0B5FA5", | ||
| "color": "white", | ||
| "padding": "15px", | ||
| "borderRadius": "8px" | ||
| } | ||
| "borderRadius": "10px", | ||
| "textAlign": "center", | ||
| "fontSize": "22px", | ||
| "fontWeight": "bold", | ||
| }, | ||
| ), | ||
|
|
||
| html.Br(), | ||
|
|
||
|
|
||
| html.Div( | ||
| children=[ | ||
| html.H3("Filters"), | ||
| html.P("Add dropdowns / filters here") | ||
| ], | ||
| "This dashboard summarizes posting dynamics, linguistic distribution, platform sources, and key thematic patterns extracted from the dataset.", | ||
| style={ | ||
| "backgroundColor": "#E6F4F9", | ||
| "padding": "15px", | ||
| "borderRadius": "8px" | ||
| } | ||
| "textAlign": "center", | ||
| "marginTop": "6px", | ||
| "marginBottom": "16px", | ||
| "color": "#6B7280", | ||
| "fontSize": "12.5px", | ||
| "fontStyle": "italic", | ||
| }, | ||
| ), | ||
|
|
||
| html.Br(), | ||
|
|
||
|
|
||
| # GRAPHS GRID PROPRE | ||
| html.Div( | ||
| style={ | ||
| "display": "grid", | ||
| "gridTemplateColumns": "1fr 1fr", | ||
| "gap": "15px", | ||
| }, | ||
| children=[ | ||
| html.H3("Visualizations"), | ||
| html.P("Graphs will be added here") | ||
|
|
||
| dcc.Graph(figure=trend), | ||
| dcc.Graph(figure=lang), | ||
|
|
||
| dcc.Graph(figure=source), | ||
| dcc.Graph(figure=themes), | ||
| ], | ||
| style={ | ||
| "backgroundColor": "#F5F5F5", | ||
| "padding": "20px", | ||
| "borderRadius": "8px" | ||
| } | ||
| ) | ||
| ] | ||
| ), | ||
| ], | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| import pandas as pd | ||
| import plotly.graph_objects as go | ||
|
|
||
| DATA_PATH = "data/PGP x D4G- Exported Vaccine Data.xlsx" # Correct to the actual Excel file | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Je ne vois pas le fichier dans
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. D’accord |
||
|
|
||
| # ── Load all sheets ──────────────────────────────────────────────── | ||
| xl = pd.ExcelFile(DATA_PATH) | ||
|
|
||
| df_trend = pd.read_excel(xl, "Trendline") | ||
| df_trend.columns = ["date", "posts"] | ||
| df_trend["date"] = pd.to_datetime(df_trend["date"]) | ||
|
|
||
| df_lang = pd.read_excel(xl, "Language") | ||
| df_lang.columns = ["language", "posts", "share"] | ||
| df_lang = df_lang.dropna(subset=["language", "posts"]) | ||
| df_lang = df_lang[df_lang["posts"].apply(lambda x: str(x).isdigit() or isinstance(x, (int, float)))] | ||
| df_lang["posts"] = pd.to_numeric(df_lang["posts"], errors="coerce") | ||
| df_lang = df_lang.dropna(subset=["posts"]).head(8) | ||
|
|
||
| df_source = pd.read_excel(xl, "Source") | ||
| df_source.columns = ["source", "mentions"] | ||
| df_source["mentions"] = pd.to_numeric(df_source["mentions"], errors="coerce").fillna(0) | ||
| df_source = df_source.dropna(subset=["source", "mentions"]) | ||
|
|
||
| df_themes_raw = pd.read_excel(xl, "Crosstab- themes across all vac") | ||
|
|
||
| # Corrected processing for df_th | ||
| df_th = df_themes_raw.drop(columns=['Topics \\ Themes']).T.reset_index() | ||
| df_th.columns = ['theme', 'mentions'] | ||
| df_th['mentions'] = pd.to_numeric(df_th['mentions'], errors='coerce') | ||
| df_th = df_th.dropna(subset=["mentions"]) | ||
| df_th = df_th.sort_values("mentions", ascending=False) | ||
|
|
||
| PALETTE = ["#1E5AA8", "#2F6FB6", "#5C8FD6", "#E6EEF8"] | ||
| BG = "#FFFFFF" | ||
| PAPER = "#FFFFFF" | ||
| FONT_COLOR = "#333333" | ||
| GRID_COLOR = "#E0E0E0" | ||
|
|
||
|
|
||
| def base_layout(title): | ||
| return dict( | ||
| title=dict(text=title, font=dict(size=16, color=FONT_COLOR), x=0.02), | ||
| paper_bgcolor=PAPER, | ||
| plot_bgcolor=BG, | ||
| font=dict(family="Inter, sans-serif", color=FONT_COLOR), | ||
| margin=dict(l=50, r=30, t=60, b=50), | ||
| ) | ||
|
|
||
|
|
||
| # ── 1. Daily post volume trendline ───────────────────────────── | ||
| fig_trend = go.Figure() | ||
| fig_trend.add_trace(go.Scatter( | ||
| x=df_trend["date"], y=df_trend["posts"], | ||
| mode="lines+markers", | ||
| line=dict(color=PALETTE[0], width=2), | ||
| marker=dict(size=5, color=PALETTE[0]), | ||
| fill="tozeroy", | ||
| fillcolor="rgba(30,90,168,0.15)", | ||
| name="Posts", | ||
| hovertemplate="%{x|%b %d}<br><b>%{y:,}</b> posts<extra></extra>", | ||
| )) | ||
| fig_trend.update_layout( | ||
| **base_layout("Daily Post Volume — March–April 2026"), | ||
| xaxis=dict(showgrid=False, tickformat="%b %d", tickcolor=GRID_COLOR), | ||
| yaxis=dict(showgrid=True, gridcolor=GRID_COLOR, tickformat=","), | ||
| ) | ||
|
|
||
| # ── 2. Language donut ─────────────────────────────────── | ||
| fig_lang = go.Figure(go.Pie( | ||
| labels=df_lang["language"], | ||
| values=df_lang["posts"], | ||
| hole=0.55, | ||
| marker=dict(colors=PALETTE), | ||
| textinfo="label+percent", | ||
| hovertemplate="<b>%{label}</b><br>%{value:,} posts (%{percent})<extra></extra>", | ||
| )) | ||
| fig_lang.update_layout( | ||
| **base_layout("Post Distribution by Language"), | ||
| showlegend=False, | ||
| ) | ||
|
|
||
| # Create a color list for df_source that matches its length | ||
| source_colors = [] | ||
| for i in range(len(df_source)): | ||
| source_colors.append(PALETTE[i % len(PALETTE)]) | ||
|
|
||
| # ── 3. Source donut chart ─────────────────────────────────── | ||
| fig_source = go.Figure(go.Pie( | ||
| labels=df_source["source"].tolist(), | ||
| values=df_source["mentions"].tolist(), | ||
| hole=0.55, | ||
| marker=dict(colors=source_colors), # Use the explicit color list | ||
| textinfo="label+percent", # Reverted to include percentage | ||
| hovertemplate="<b>%{label}</b><br>%{value:,} mentions (%{percent})<extra></extra>", # Reverted to include percentage | ||
| )) | ||
| fig_source.update_layout( | ||
| **base_layout("Mentions by Platform"), | ||
| showlegend=False, | ||
| ) | ||
|
|
||
| # ── 4. Anti-vaccine themes treemap ───────────────────── | ||
| # Define a colorscale using the PALETTE in reverse order to map higher mentions to darker blues | ||
| gradient_colors = [[0, PALETTE[3]], [0.33, PALETTE[2]], [0.66, PALETTE[1]], [1, PALETTE[0]]] | ||
| fig_themes = go.Figure(go.Treemap( | ||
| labels=df_th["theme"], | ||
| parents=[""] * len(df_th), | ||
| values=df_th["mentions"], | ||
| # Assign the 'mentions' column to marker.colors for the gradient effect | ||
| marker=dict(colors=df_th["mentions"], colorscale=gradient_colors, showscale=False), | ||
| hovertemplate="<b>%{label}</b><br>%{value:,} mentions (%{percent parent})<extra></extra>", | ||
| textinfo="label+percent parent" | ||
| )) | ||
| fig_themes.update_layout(**base_layout("Anti-vaccine Themes — All Vaccines")) | ||
| fig_themes.update_layout(margin=dict(l=10, r=10, t=60, b=10)) | ||
|
|
||
| __all__ = ["get_figures"] | ||
|
|
||
| def get_figures(): | ||
| return ( | ||
| fig_trend, | ||
| fig_lang, | ||
| fig_source, | ||
| fig_themes | ||
| ) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comme ce fichier n'est pas une page, je le mettrai dans "/utils" plutôt que "/pages".