admin管理员组

文章数量:1298409

How can I implement functionality in my Streamlit app where a sidebar is displayed only in one specific tab, and after entering all the details in that tab, the sidebar automatically closes when navigating to other tabs, but reopens when navigating back to the specific tab?

def main():
    col1, col2 = st.columns([1, 12])  # Adjust ratios to control the width of each column

    with col2:
    # Title on the left
        st.title("Business Heuristic Model")

    with col1:
        # Image on the right
        st.image("download.jpg", width=100)

    tab1, tab2, tab3, tab4 = st.tabs(["Home", "Archetype filtration", "Modeling and analysis", "Download results"])
    if "archetype_selected" not in st.session_state:
        st.session_state["archetype_selected"] = False
    if "features_selected" not in st.session_state:
        st.session_state["features_selected"] = False
    if "sidebar_score" not in st.session_state:
        st.session_state["sidebar_score"] = False
    
    if 'filtered_df' not in locals():
        filtered_df=None
    if 'selected_features' not in locals():
        selected_features = []
    if 'scored_df' not in locals():
        scored_df=None
    
    with tab1:
        st.header("Upload data file")
        uploaded_file = st.file_uploader(
            "", type=["csv", "xlsx", "json", "pkl", "txt"]
        )
        if uploaded_file is not None:
            st.success("File uploaded successfully!")
        else:
            st.warning("**Disclaimer:** Please ensure that the uploaded file contains only the required columns for analysis.")
            # st.info("Please upload a file to begin.")

    with tab2:
        if uploaded_file is not None:
            df = read_file(uploaded_file)
            # high_cardinality_columns = identify_high_cardinality_columns(df)
            # st.write("High Cardinality Columns:", high_cardinality_columns)
            filtered_df = archetype_selection_and_filtration(df)

            if filtered_df is not None and not filtered_df.empty:
                if "archetype_selected" not in st.session_state:  # Initialize state
                    st.session_state["archetype_selected"] = False
                    st.session_state["features_selected"] = False
                    st.session_state["sidebar_score"] = False

                if st.button("Submit Archetype Selection"):
                    st.success("Archetype selected successfully!")
                    st.session_state["archetype_selected"] = True
                    st.session_state["features_selected"] = False


    with tab3:
        if filtered_df is not None and not filtered_df.empty:
            if st.session_state["archetype_selected"] and not st.session_state["features_selected"]:
                selected_features = feature_selection(
                    filtered_df, selected_features, "id2", "name2", "status2"
                )
                # if st.button("Submit Feature Selection"):
                #     st.session_state["Submit Feature Selection"] = True

                # if st.session_state["Submit Feature Selection"]:
                #     st.success("Feature selection submitted.")

                if selected_features:
                    st.session_state["sidebar_score"] = True
                # else:
                #     st.sidebar.write("No features selected.")
            else:
                st.warning(
                    "No data available after filtering. Please select a valid category and press submit button"
                )

            # Sidebar - Weight and Score Adjustments
            if st.session_state["sidebar_score"]:
                weights_dict = {}
                scores_dict = {}
                with st.sidebar.header("Adjust Weights"):
                    for idx, feature in enumerate(selected_features):
                        unique_key = f"weight_{feature}_{idx}"
                        weights_dict[feature] = st.sidebar.slider(
                            f"{feature}", min_value=0, max_value=10, value=1, key=unique_key
                        )

                with st.sidebar.header("Adjust Scores"):
                    for feature in selected_features:
                        st.sidebar.subheader(feature)
                        # unique_values = filtered_df[feature].unique()
                        unique_values = sorted(filtered_df[feature].unique())
                        scores_dict[feature] = {}
                        for idx, value in enumerate(unique_values):
                            unique_key = f"{feature}_{value}_{idx}"
                            scores_dict[feature][value] = st.sidebar.slider(
                                f"{value}",
                                min_value=0,
                                max_value=100,
                                value=50,
                                step=5,
                                key=unique_key
                            )

                # Call the scoring function after adjustments
                inflator_deflator_dict = get_inflator_deflator_dict(filtered_df)

                # if st.button("Submit Inflator/Deflator Selection"):
                #     st.success("Inflator/Deflator selection submitted.")

                # Automatically process and score data when slider values are changed
                scored_df = process_and_score_data(
                    df=filtered_df,
                    weights_dict=weights_dict,
                    scores_dict=scores_dict,
                    feature_list=list(weights_dict.keys()),
                    inflator_deflator_dict=inflator_deflator_dict,
                )

                # Display the scored DataFrame
                st.header("Scored Data")
                st.write(scored_df.head())

                st.header("Charts")

                selected_columns = get_selected_columns()
                # column1 = selected_columns["column1"]
                column3 = selected_columns["column3"]

                # Distribution of scores
                st.write(f"Customer Status Column: {column3}")
       

                scored_df = create_propensity_tiers(scored_df)
                display_feature_distribution_charts(scored_df, selected_features, column3)
                display_additional_charts(scored_df, selected_features, column3)
                # display_feature_importance(weights_dict)
            # else:
            #     st.error("The uploaded file could not be read or is empty.")
    # else:
    #     st.info("Please upload a file to begin.")
    with tab4:
        if scored_df is not None and not scored_df.empty:
            st.write("Scored Data:")
            st.dataframe(scored_df)

            # st.write("Selected Features and their Weights and Scores:")
            sorted_features = sorted(selected_features, key=lambda x: weights_dict.get(x, 0), reverse=True)
            # for feature in selected_features:
            for feature in sorted_features:
                st.header(f"{feature}")
                st.subheader(f"Assigned weight: {weights_dict.get(feature, 'N/A')}")
                st.subheader("Assigned scores:")
                scores_df = pd.DataFrame(list(scores_dict.get(feature, {}).items()), columns=["Category", "Score"]).sort_values(by="Score", ascending=False)
                st.table(scores_df)
       
            download_options = st.multiselect(
                "Select items to download:",
                options=["Scored data", "Weights, scores and inflator/deflators", "HTML of charts"],
                default=[]
            )

            # Download button
            if download_options:
                if "Scored data" in download_options:
                    scored_data_excel = BytesIO()
                    with pd.ExcelWriter(scored_data_excel, engine='xlsxwriter') as writer:
                        scored_df.to_excel(writer, index=False, sheet_name='Scored Data')
                    st.download_button(
                        label="Download scored data",
                        data=scored_data_excel.getvalue(),
                        file_name="scored_data.xlsx",
                        mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                    )
                if "Weights, scores and inflator/deflators" in download_options:
                    weights_df = pd.DataFrame(list(weights_dict.items()), columns=["Feature", "Weight"])
                    scores_combined_df = pd.concat(
                        [pd.DataFrame({"Feature": feature, "Category": list(scores_dict[feature].keys()), "Score": list(scores_dict[feature].values())}) for feature in scores_dict],
                        ignore_index=True
                    )
                    combined_df = pd.merge(scores_combined_df, weights_df, on="Feature", how="left")
                    
                    # Convert inflator_deflator_dict to DataFrame
                    inflator_deflator_list = []
                    for feature, values in inflator_deflator_dict.items():
                        for category, inflator_deflator_value in values.items():
                            inflator_deflator_list.append({"Feature": feature, "Category": category, "Inflator/Deflator": inflator_deflator_value})
                    inflator_deflator_df = pd.DataFrame(inflator_deflator_list)

                    combined_excel = BytesIO()
                    with pd.ExcelWriter(combined_excel, engine='xlsxwriter') as writer:
                        combined_df.to_excel(writer, index=False, sheet_name='Weights_and_Scores')
                        inflator_deflator_df.to_excel(writer, index=False, sheet_name='Inflator_Deflator')
                    st.download_button(
                        label="Download weights, scores and inflator/deflators",
                        data=combined_excel.getvalue(),
                        file_name="weights_and_scores.xlsx",
                        mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                    )

                if "HTML of charts" in download_options:
                    html_content = "<html><head><title>Charts Report</title></head><body style='width: 100%; text-align: center;'>"
                    for fig_num in plt.get_fignums():
                        fig = plt.figure(fig_num)
                        buf = BytesIO()
                        fig.savefig(buf, format="png", bbox_inches='tight')
                        buf.seek(0)
                        img_base64 = base64.b64encode(buf.read()).decode("utf-8")
                        html_content += f'<img src="data:image/png;base64,{img_base64}" style="width: 80%; margin: 0 auto; display: block;"/><br>'
                    html_content += "</body></html>"

                    st.download_button(
                        label="Download HTML of charts",
                        data=html_content,
                        file_name="charts_report.html",
                        mime="text/html"
                    )
                    
if __name__ == "__main__":
    main()

本文标签: