import streamlit as st # CSS inchangé st.markdown(""" """, unsafe_allow_html=True) st.set_page_config(page_title="Bayes – Calcul rapide", layout="wide") st.title("🧠 Bayes – Calcul interactif") st.caption("P(A|B) = [P(B|A) × P(A)] / P(B)") with st.expander("Rappel formule", expanded=False): st.markdown("P(B) = P(B|A)×P(A) + P(B|¬A)×P(¬A)") # ─── Mode + select ──────────────────────────────────────────────────────── col_mode, col_ex = st.columns([40, 60]) with col_mode: mode_ds = st.toggle("Mode Data Science (Recall/Precision)", value=False) if mode_ds: lbl = { "prev": "Prévalence (Classe +)", "recall": "Recall (Sensibilité)", "spe": "Spécificité (TNR)", "post": "Précision (VPP)", } else: lbl = { "prev": "Prior P(A)", "recall": "Sensibilité P(+|A)", "spe": "Spécificité P(-|¬A)", "post": "Postérieur P(A|+)", } with col_ex: exemples = [ "Manuel", "Cancer dépistage ~0.8%", "Fraude CB ~0.1%", "Grossesse ~4–5%", "ADN culpabilité ~0.001%" ] choix = st.selectbox("Exemple", exemples, index=0, key="exemple_select") # Détection changement + suffix pour clés dynamiques if "prev_choix" not in st.session_state: st.session_state.prev_choix = "INIT" exemple_changed = choix != st.session_state.prev_choix key_suffix = f"_{choix.replace(' ', '_')}" if exemple_changed else "" # Mise à jour st.session_state.prev_choix = choix # Defaults defaults = { "Cancer dépistage ~0.8%": (0.8, 85.0, 92.0), "Fraude CB ~0.1%": (0.1, 92.0, 99.85), "Grossesse ~4–5%": (4.5, 99.0, 99.5), "ADN culpabilité ~0.001%": (0.001, 99.9, 99.99), }.get(choix, (5.0, 90.0, 95.0)) # ─── Inputs avec clés dynamiques quand changement ───────────────────────── c1, c2, c3, c4 = st.columns(4, gap="small") with c1: st.caption(f"{lbl['prev']} (%)") prev = st.number_input( label = lbl['prev'], min_value = 0.0, max_value = 100.0, value = float(defaults[0]), step = 0.01, key = f"prev{key_suffix}", label_visibility = "collapsed" ) with c2: st.caption(f"{lbl['recall']} (%)") recall = st.number_input( label = lbl['recall'], min_value = 0.0, max_value = 100.0, value = float(defaults[1]), step = 0.1, key = f"rec{key_suffix}", label_visibility = "collapsed" ) with c3: st.caption(f"{lbl['spe']} (%)") speci = st.number_input( label = lbl['spe'], min_value = 0.0, max_value = 100.0, value = float(defaults[2]), step = 0.1, key = f"spe{key_suffix}", label_visibility = "collapsed" ) with c4: st.caption(f"{lbl['post']} (%)") post = st.number_input( label = lbl['post'], min_value = 0.0, max_value = 100.0, value = 50.0, step = 0.1, key = f"post{key_suffix}", label_visibility = "collapsed" ) # ─── Checkboxes (inchangées, mais on peut les reset si tu veux) ─────────── st.write("") st.subheader("Calculer :", divider=False) cols = st.columns(4, gap="small") calc_prev = cols[0].checkbox(lbl["prev"], key="c_prev") calc_recall = cols[1].checkbox(lbl["recall"], key="c_rec") calc_speci = cols[2].checkbox(lbl["spe"], key="c_spe") calc_post = cols[3].checkbox(lbl["post"], value=True, key="c_post") # Bouton Calculer (inchangé) if st.button("Calculer", type="primary", use_container_width=True): p = prev / 100 se = recall / 100 sp = speci / 100 po = post / 100 checked = sum([calc_prev, calc_recall, calc_speci, calc_post]) if checked != 1: st.error("Cocher **exactement une** grandeur à calculer") else: try: res = None label = "" if calc_post: res = (se * p) / (se * p + (1 - sp) * (1 - p)) label = lbl["post"] elif calc_prev: res = (po * (1 - sp)) / (se - po * (se - (1 - sp))) label = lbl["prev"] elif calc_recall: res = (po * (1 - sp) * (1 - p)) / (p * (1 - po)) label = lbl["recall"] elif calc_speci: res = 1 - (se * p * (1 - po)) / (po * (1 - p)) label = lbl["spe"] res_pct = res * 100 if 0 <= res <= 1: st.success(f"**{label} = {res_pct:,.3f} %**") else: st.warning(f"Résultat : {res_pct:,.2f} % → paramètres incohérents") except ZeroDivisionError: st.error("Division par zéro – vérifiez les valeurs extrêmes") except Exception as e: st.error(f"Erreur : {str(e)}") # Sources et astuce (inchangés) with st.expander("Sources et références des exemples", expanded=False): st.markdown("... ton contenu ...") with st.expander("Astuce rapide", expanded=False): st.caption("Plus la prévalence est faible → plus la précision chute...")