feat(explorer): add _render_party_axis_chart helper
This commit is contained in:
+67
@@ -203,6 +203,73 @@ def load_party_map(db_path: str) -> Dict[str, str]:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def _render_party_axis_chart(
|
||||||
|
party_scores: Dict[str, List[float]], comp_sel: int
|
||||||
|
) -> None:
|
||||||
|
"""Render a 1D horizontal Plotly scatter of party positions on SVD axis `comp_sel`.
|
||||||
|
|
||||||
|
Each party is plotted at its score on a single horizontal axis (y=0).
|
||||||
|
"""
|
||||||
|
if not party_scores:
|
||||||
|
st.caption("_Partijdata niet beschikbaar voor deze as._")
|
||||||
|
return
|
||||||
|
|
||||||
|
axis_idx = comp_sel - 1 # 0-based index into the 50-dim vector
|
||||||
|
data: list[dict] = []
|
||||||
|
for party, vec in party_scores.items():
|
||||||
|
if axis_idx < len(vec):
|
||||||
|
data.append({"party": party, "score": vec[axis_idx]})
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
st.caption("_Geen partijscores voor deze as._")
|
||||||
|
return
|
||||||
|
|
||||||
|
scores = [d["score"] for d in data]
|
||||||
|
parties = [d["party"] for d in data]
|
||||||
|
colours = [PARTY_COLOURS.get(p, "#9E9E9E") for p in parties]
|
||||||
|
hover = [f"{p}: {s:.3f}" for p, s in zip(parties, scores)]
|
||||||
|
|
||||||
|
fig = go.Figure()
|
||||||
|
# Baseline
|
||||||
|
x_min, x_max = min(scores) * 1.15, max(scores) * 1.15
|
||||||
|
fig.add_trace(
|
||||||
|
go.Scatter(
|
||||||
|
x=[x_min, x_max],
|
||||||
|
y=[0, 0],
|
||||||
|
mode="lines",
|
||||||
|
line={"color": "#cccccc", "width": 1},
|
||||||
|
hoverinfo="skip",
|
||||||
|
showlegend=False,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Party markers
|
||||||
|
fig.add_trace(
|
||||||
|
go.Scatter(
|
||||||
|
x=scores,
|
||||||
|
y=[0] * len(scores),
|
||||||
|
mode="markers+text",
|
||||||
|
text=parties,
|
||||||
|
textposition="top center",
|
||||||
|
marker={"size": 12, "color": colours},
|
||||||
|
hovertext=hover,
|
||||||
|
hoverinfo="text",
|
||||||
|
showlegend=False,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fig.update_layout(
|
||||||
|
height=160,
|
||||||
|
margin={"l": 10, "r": 10, "t": 10, "b": 30},
|
||||||
|
xaxis={
|
||||||
|
"title": "← Negatieve pool | Positieve pool →",
|
||||||
|
"zeroline": True,
|
||||||
|
"zerolinecolor": "#aaaaaa",
|
||||||
|
},
|
||||||
|
yaxis={"visible": False, "range": [-1, 2]},
|
||||||
|
plot_bgcolor="white",
|
||||||
|
)
|
||||||
|
st.plotly_chart(fig, use_container_width=True)
|
||||||
|
|
||||||
|
|
||||||
@st.cache_data(show_spinner="Moties laden…")
|
@st.cache_data(show_spinner="Moties laden…")
|
||||||
def load_motions_df(db_path: str) -> pd.DataFrame:
|
def load_motions_df(db_path: str) -> pd.DataFrame:
|
||||||
"""Load the full motions table as a pandas DataFrame (read-only)."""
|
"""Load the full motions table as a pandas DataFrame (read-only)."""
|
||||||
|
|||||||
Reference in New Issue
Block a user