Spaces:
Sleeping
Sleeping
GMARTINEZMILLA
commited on
Commit
•
768acc0
1
Parent(s):
65cad3a
bugfix: Manufacturers Alerts
Browse files
app.py
CHANGED
@@ -680,285 +680,34 @@ elif page == "Customer Analysis":
|
|
680 |
else:
|
681 |
st.warning(f"No predicted or actual data found for customer {customer_code} for 2024.")
|
682 |
|
683 |
-
|
684 |
-
|
685 |
-
# elif page == "Customer Analysis":
|
686 |
-
# st.markdown("""
|
687 |
-
# <h2 style='text-align: center; font-size: 2.5rem;'>Customer Analysis</h2>
|
688 |
-
# <p style='text-align: center; font-size: 1.2rem; color: gray;'>
|
689 |
-
# Enter the customer code to explore detailed customer insights,
|
690 |
-
# including past sales, predictions for the current year, and manufacturer-specific information.
|
691 |
-
# </p>
|
692 |
-
# """, unsafe_allow_html=True)
|
693 |
-
|
694 |
-
# # Combine text input and dropdown into a single searchable selectbox
|
695 |
-
# customer_code = st.selectbox(
|
696 |
-
# "Search and Select Customer Code",
|
697 |
-
# df['CLIENTE'].unique(), # All customer codes
|
698 |
-
# format_func=lambda x: str(x), # Ensures the values are displayed as strings
|
699 |
-
# help="Start typing to search for a specific customer code"
|
700 |
-
# )
|
701 |
-
|
702 |
-
# if st.button("Calcular"):
|
703 |
-
# if customer_code:
|
704 |
-
# with st.spinner("We are identifying the customer's cluster..."):
|
705 |
-
# # Find Customer's Cluster
|
706 |
-
# customer_match = customer_clusters[customer_clusters['cliente_id'] == customer_code]
|
707 |
-
# time.sleep(1)
|
708 |
-
|
709 |
-
|
710 |
-
# if not customer_match.empty:
|
711 |
-
# cluster = customer_match['cluster_id'].values[0]
|
712 |
-
|
713 |
-
# with st.spinner(f"Selecting predictive model..."):
|
714 |
-
# # Load the Corresponding Model
|
715 |
-
# model_path = f'models/modelo_cluster_{cluster}.txt'
|
716 |
-
# gbm = lgb.Booster(model_file=model_path)
|
717 |
-
|
718 |
-
# with st.spinner("Getting the data ready..."):
|
719 |
-
# # Load predict data for that cluster
|
720 |
-
# predict_data = pd.read_csv(f'predicts/predict_cluster_{cluster}.csv')
|
721 |
-
|
722 |
-
# # Convert cliente_id to string
|
723 |
-
# predict_data['cliente_id'] = predict_data['cliente_id'].astype(str)
|
724 |
-
|
725 |
-
# with st.spinner("Filtering data..."):
|
726 |
-
|
727 |
-
# # Filter for the specific customer
|
728 |
-
# customer_code_str = str(customer_code)
|
729 |
-
# customer_data = predict_data[predict_data['cliente_id'] == customer_code_str]
|
730 |
-
|
731 |
-
# with st.spinner("Generating sales predictions..."):
|
732 |
-
|
733 |
-
# if not customer_data.empty:
|
734 |
-
# # Define features consistently with the training process
|
735 |
-
# lag_features = [f'precio_total_lag_{lag}' for lag in range(1, 25)]
|
736 |
-
# features = lag_features + ['mes', 'marca_id_encoded', 'año', 'cluster_id']
|
737 |
-
|
738 |
-
# # Prepare data for prediction
|
739 |
-
# X_predict = customer_data[features]
|
740 |
-
|
741 |
-
# # Convert categorical features to 'category' dtype
|
742 |
-
# categorical_features = ['mes', 'marca_id_encoded', 'cluster_id']
|
743 |
-
# for feature in categorical_features:
|
744 |
-
# X_predict[feature] = X_predict[feature].astype('category')
|
745 |
-
|
746 |
-
# # Make Prediction for the selected customer
|
747 |
-
# y_pred = gbm.predict(X_predict, num_iteration=gbm.best_iteration)
|
748 |
-
|
749 |
-
# # Reassemble the results
|
750 |
-
# results = customer_data[['cliente_id', 'marca_id_encoded', 'fecha_mes']].copy()
|
751 |
-
# results['ventas_predichas'] = y_pred
|
752 |
-
|
753 |
-
# # Load actual data
|
754 |
-
# actual_sales = df_agg_2024[df_agg_2024['cliente_id'] == customer_code_str]
|
755 |
-
|
756 |
-
# if not actual_sales.empty:
|
757 |
-
# results = results.merge(actual_sales[['cliente_id', 'marca_id_encoded', 'fecha_mes', 'precio_total']],
|
758 |
-
# on=['cliente_id', 'marca_id_encoded', 'fecha_mes'],
|
759 |
-
# how='left')
|
760 |
-
# results.rename(columns={'precio_total': 'ventas_reales'}, inplace=True)
|
761 |
-
# results['ventas_reales'].fillna(0, inplace=True)
|
762 |
-
# # st.write("### Final Results DataFrame:")
|
763 |
-
# # st.write(results.head())
|
764 |
-
# # st.write(f"Shape: {results.shape}")
|
765 |
-
|
766 |
-
# # Calculate metrics only for non-null actual sales
|
767 |
-
# valid_results = results.dropna(subset=['ventas_reales'])
|
768 |
-
# non_zero_actuals = valid_results[valid_results['ventas_reales'] != 0]
|
769 |
-
# if not valid_results.empty:
|
770 |
-
# mae = mean_absolute_error(valid_results['ventas_reales'], valid_results['ventas_predichas'])
|
771 |
-
# mape = np.mean(np.abs((non_zero_actuals['ventas_reales'] - non_zero_actuals['ventas_predichas']) / non_zero_actuals['ventas_reales'])) * 100
|
772 |
-
# rmse = np.sqrt(mean_squared_error(valid_results['ventas_reales'], valid_results['ventas_predichas']))
|
773 |
-
|
774 |
-
# # st.write(f"Actual total sales for Customer {customer_code}: {valid_results['ventas_reales'].sum():.2f}")
|
775 |
-
# # st.write(f"MAE: {mae:.2f}€")
|
776 |
-
# # st.write(f"MAPE: {mape:.2f}%")
|
777 |
-
# # st.write(f"RMSE: {rmse:.2f}")
|
778 |
-
|
779 |
-
# # # Analysis of results
|
780 |
-
# # threshold_good = 100 # You may want to adjust this threshold
|
781 |
-
# # if mae < threshold_good:
|
782 |
-
# # st.success(f"Customer {customer_code} is performing well based on the predictions.")
|
783 |
-
# # else:
|
784 |
-
# # st.warning(f"Customer {customer_code} is not performing well based on the predictions.")
|
785 |
-
# # else:
|
786 |
-
# # st.warning(f"No actual sales data found for customer {customer_code} in df_agg_2024.")
|
787 |
-
|
788 |
-
# # st.write("### Debug Information for Radar Chart:")
|
789 |
-
# # st.write(f"Shape of customer_data: {customer_data.shape}")
|
790 |
-
# # st.write(f"Shape of euros_proveedor: {euros_proveedor.shape}")
|
791 |
-
|
792 |
-
# # Get percentage of units sold for each manufacturer
|
793 |
-
# customer_df = df[df["CLIENTE"] == str(customer_code)] # Get the customer data
|
794 |
-
# all_manufacturers = customer_df.iloc[:, 1:].T # Exclude CLIENTE column (manufacturers are in columns)
|
795 |
-
# all_manufacturers.index = all_manufacturers.index.astype(str)
|
796 |
-
|
797 |
-
# # Get total sales for each manufacturer from euros_proveedor
|
798 |
-
# customer_euros = euros_proveedor[euros_proveedor["CLIENTE"] == str(customer_code)]
|
799 |
-
# sales_data = customer_euros.iloc[:, 1:].T # Exclude CLIENTE column
|
800 |
-
# sales_data.index = sales_data.index.astype(str)
|
801 |
-
|
802 |
-
# # Remove the 'CLIENTE' row from sales_data to avoid issues with mixed types
|
803 |
-
# sales_data_filtered = sales_data.drop(index='CLIENTE', errors='ignore')
|
804 |
-
|
805 |
-
# # Ensure all values are numeric
|
806 |
-
# sales_data_filtered = sales_data_filtered.apply(pd.to_numeric, errors='coerce')
|
807 |
-
# all_manufacturers = all_manufacturers.apply(pd.to_numeric, errors='coerce')
|
808 |
-
|
809 |
-
# # Sort manufacturers by percentage of units and get top 10
|
810 |
-
# top_units = all_manufacturers.sort_values(by=all_manufacturers.columns[0], ascending=False).head(10)
|
811 |
-
|
812 |
-
# # Sort manufacturers by total sales and get top 10
|
813 |
-
# top_sales = sales_data_filtered.sort_values(by=sales_data_filtered.columns[0], ascending=False).head(10)
|
814 |
-
|
815 |
-
# # Combine top manufacturers from both lists and get up to 20 unique manufacturers
|
816 |
-
# combined_top = pd.concat([top_units, top_sales]).index.unique()[:20]
|
817 |
-
|
818 |
-
# # Filter out manufacturers that are not present in both datasets
|
819 |
-
# combined_top = [m for m in combined_top if m in all_manufacturers.index and m in sales_data_filtered.index]
|
820 |
-
|
821 |
-
# # st.write(f"Number of combined top manufacturers: {len(combined_top)}")
|
822 |
-
|
823 |
-
# if combined_top:
|
824 |
-
# # Create a DataFrame with combined data for these top manufacturers
|
825 |
-
# combined_data = pd.DataFrame({
|
826 |
-
# 'units': all_manufacturers.loc[combined_top, all_manufacturers.columns[0]],
|
827 |
-
# 'sales': sales_data_filtered.loc[combined_top, sales_data_filtered.columns[0]]
|
828 |
-
# }).fillna(0)
|
829 |
-
|
830 |
-
# # Sort by units, then by sales
|
831 |
-
# combined_data_sorted = combined_data.sort_values(by=['units', 'sales'], ascending=False)
|
832 |
-
|
833 |
-
# # Filter out manufacturers with 0 units
|
834 |
-
# non_zero_manufacturers = combined_data_sorted[combined_data_sorted['units'] > 0]
|
835 |
-
|
836 |
-
# # If we have less than 3 non-zero manufacturers, add some zero-value ones
|
837 |
-
# if len(non_zero_manufacturers) < 3:
|
838 |
-
# zero_manufacturers = combined_data_sorted[combined_data_sorted['units'] == 0].head(3 - len(non_zero_manufacturers))
|
839 |
-
# manufacturers_to_show = pd.concat([non_zero_manufacturers, zero_manufacturers])
|
840 |
-
# else:
|
841 |
-
# manufacturers_to_show = non_zero_manufacturers
|
842 |
-
|
843 |
-
# values = manufacturers_to_show['units'].tolist()
|
844 |
-
# amounts = manufacturers_to_show['sales'].tolist()
|
845 |
-
# manufacturers = [get_supplier_name(m) for m in manufacturers_to_show.index]
|
846 |
-
|
847 |
-
# # st.write(f"### Results for top {len(manufacturers)} manufacturers:")
|
848 |
-
# # for manufacturer, value, amount in zip(manufacturers, values, amounts):
|
849 |
-
# # (f"{manufacturer} = {value:.2f}% of units, €{amount:.2f} total sales")
|
850 |
-
|
851 |
-
# if manufacturers: # Only create the chart if we have data
|
852 |
-
# fig = radar_chart(manufacturers, values, amounts, f'Radar Chart for Top {len(manufacturers)} Manufacturers of Customer {customer_code}')
|
853 |
-
# st.pyplot(fig)
|
854 |
-
# else:
|
855 |
-
# st.warning("No data available to create the radar chart.")
|
856 |
-
|
857 |
-
# else:
|
858 |
-
# st.warning("No combined top manufacturers found.")
|
859 |
-
|
860 |
-
# # Ensure codigo_cliente in ventas_clientes is a string
|
861 |
-
# ventas_clientes['codigo_cliente'] = ventas_clientes['codigo_cliente'].astype(str).str.strip()
|
862 |
-
|
863 |
-
# # Ensure customer_code is a string and strip any spaces
|
864 |
-
# customer_code = str(customer_code).strip()
|
865 |
-
|
866 |
-
# # if customer_code in ventas_clientes['codigo_cliente'].unique():
|
867 |
-
# # (f"Customer {customer_code} found in ventas_clientes")
|
868 |
-
# # else:
|
869 |
-
# # (f"Customer {customer_code} not found in ventas_clientes")
|
870 |
-
|
871 |
-
# # Customer sales 2021-2024 (if data exists)
|
872 |
-
# sales_columns = ['VENTA_2021', 'VENTA_2022', 'VENTA_2023']
|
873 |
-
# if all(col in ventas_clientes.columns for col in sales_columns):
|
874 |
-
# customer_sales_data = ventas_clientes[ventas_clientes['codigo_cliente'] == customer_code]
|
875 |
-
|
876 |
-
# if not customer_sales_data.empty:
|
877 |
-
# customer_sales = customer_sales_data[sales_columns].values[0]
|
878 |
-
# years = ['2021', '2022', '2023']
|
879 |
-
|
880 |
-
# # Add the 2024 actual and predicted data
|
881 |
-
# if 'ventas_predichas' in results.columns and 'ventas_reales' in results.columns:
|
882 |
-
# # Get the actual and predicted sales for 2024
|
883 |
-
# actual_sales_2024 = results[results['fecha_mes'].str.startswith('2024')]['ventas_reales'].sum()
|
884 |
-
# predicted_sales_2024 = results[results['fecha_mes'].str.startswith('2024')]['ventas_predichas'].sum()
|
885 |
-
|
886 |
-
# # Estimate full-year predicted sales (assuming predictions available until September)
|
887 |
-
# months_available = 9 # Data available until September
|
888 |
-
# actual_sales_2024_annual = (actual_sales_2024 / months_available) * 12
|
889 |
-
|
890 |
-
# # Add 2024 actual and predicted sales
|
891 |
-
# sales_values = list(customer_sales) + [actual_sales_2024_annual] # Actual sales
|
892 |
-
# predicted_values = list(customer_sales) + [predicted_sales_2024] # Predicted sales
|
893 |
-
|
894 |
-
# # Add 2024 to the years list
|
895 |
-
# years.append('2024')
|
896 |
-
|
897 |
-
# fig_sales_bar = go.Figure()
|
898 |
-
# # Add trace for historical sales (2021-2023)
|
899 |
-
# fig_sales_bar.add_trace(go.Bar(
|
900 |
-
# x=years[:3], # 2021, 2022, 2023
|
901 |
-
# y=sales_values[:3],
|
902 |
-
# name="Historical Sales",
|
903 |
-
# marker_color='blue'
|
904 |
-
# ))
|
905 |
-
|
906 |
-
# # Add trace for 2024 actual sales
|
907 |
-
# fig_sales_bar.add_trace(go.Bar(
|
908 |
-
# x=[years[3]], # 2024
|
909 |
-
# y=[sales_values[3]],
|
910 |
-
# name="2024 Actual Sales (Annualized)",
|
911 |
-
# marker_color='green'
|
912 |
-
# ))
|
913 |
-
|
914 |
-
# # Add trace for 2024 predicted sales
|
915 |
-
# fig_sales_bar.add_trace(go.Bar(
|
916 |
-
# x=[years[3]], # 2024
|
917 |
-
# y=[predicted_values[3]],
|
918 |
-
# name="2024 Predicted Sales",
|
919 |
-
# marker_color='orange'
|
920 |
-
# ))
|
921 |
-
|
922 |
-
# # Update layout
|
923 |
-
# fig_sales_bar.update_layout(
|
924 |
-
# title=f"Sales Over the Years for Customer {customer_code}",
|
925 |
-
# xaxis_title="Year",
|
926 |
-
# yaxis_title="Sales (€)",
|
927 |
-
# barmode='group',
|
928 |
-
# height=600,
|
929 |
-
# legend_title_text="Sales Type",
|
930 |
-
# hovermode="x unified"
|
931 |
-
# )
|
932 |
-
|
933 |
-
# # Show the interactive bar chart in Streamlit
|
934 |
-
# st.plotly_chart(fig_sales_bar, use_container_width=True)
|
935 |
-
|
936 |
-
# else:
|
937 |
-
# st.warning(f"No predicted or actual data found for customer {customer_code} for 2024.")
|
938 |
-
|
939 |
-
# else:
|
940 |
-
# st.warning(f"No historical sales data found for customer {customer_code}")
|
941 |
-
|
942 |
-
# else:
|
943 |
-
# st.warning("Sales data for 2021-2023 not available in the dataset.")
|
944 |
-
|
945 |
-
|
946 |
-
# Customer Recommendations Page
|
947 |
# Customer Recommendations Page
|
948 |
elif page == "Articles Recommendations":
|
949 |
-
|
|
|
|
|
|
|
|
|
950 |
st.markdown("""
|
951 |
-
Get tailored recommendations for your customers based on their basket
|
952 |
-
""")
|
953 |
-
st.write("Select items and assign quantities for the basket:")
|
|
|
|
|
954 |
# Mostrar lista de artículos disponibles
|
955 |
-
available_articles = productos['
|
956 |
selected_articles = st.multiselect("Select Articles", available_articles)
|
957 |
-
#
|
958 |
quantities = {}
|
959 |
-
|
960 |
-
|
961 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
962 |
# Crear una lista de artículos basada en la selección de códigos y cantidades
|
963 |
new_basket = []
|
964 |
for article in selected_articles:
|
@@ -968,155 +717,43 @@ elif page == "Articles Recommendations":
|
|
968 |
if new_basket:
|
969 |
# Procesar la lista para recomendar
|
970 |
recommendations_df = recomienda_tfid(new_basket)
|
|
|
971 |
if not recommendations_df.empty:
|
972 |
-
st.
|
973 |
-
st.dataframe(recommendations_df)
|
974 |
else:
|
975 |
-
st.warning("No recommendations found for the provided basket.")
|
976 |
else:
|
977 |
-
st.warning("Please select at least one article and set its quantity.")
|
978 |
|
979 |
# # Customer Recommendations Page
|
980 |
# elif page == "Articles Recommendations":
|
981 |
# st.title("Articles Recommendations")
|
982 |
-
|
983 |
# st.markdown("""
|
984 |
# Get tailored recommendations for your customers based on their basket.
|
985 |
# """)
|
986 |
-
|
987 |
-
# #
|
988 |
-
#
|
989 |
-
#
|
990 |
-
#
|
991 |
-
#
|
992 |
-
#
|
993 |
-
#
|
994 |
-
#
|
995 |
-
|
996 |
-
#
|
997 |
-
#
|
998 |
-
#
|
999 |
-
#
|
1000 |
-
#
|
1001 |
-
|
1002 |
-
#
|
1003 |
-
#
|
1004 |
-
#
|
1005 |
-
|
1006 |
-
#
|
1007 |
-
#
|
1008 |
-
|
1009 |
-
# # Obtener los índices de las cestas más similares
|
1010 |
-
# similar_indices = similarities.argsort()[0][-3:] # Las 3 más similares
|
1011 |
-
|
1012 |
-
# # Crear un diccionario para contar las recomendaciones
|
1013 |
-
# recommendations_count = {}
|
1014 |
-
# total_similarity = 0
|
1015 |
-
|
1016 |
-
# # Recomendar productos de cestas similares
|
1017 |
-
# for idx in similar_indices:
|
1018 |
-
# sim_score = similarities[0][idx]
|
1019 |
-
# total_similarity += sim_score
|
1020 |
-
# products = cestas.iloc[idx]['Cestas'].split()
|
1021 |
-
|
1022 |
-
# for product in products:
|
1023 |
-
# if product.strip() not in new_basket: # Evitar recomendar lo que ya está en la cesta
|
1024 |
-
# if product.strip() in recommendations_count:
|
1025 |
-
# recommendations_count[product.strip()] += sim_score
|
1026 |
-
# else:
|
1027 |
-
# recommendations_count[product.strip()] = sim_score
|
1028 |
-
|
1029 |
-
# # Calcular la probabilidad relativa de cada producto recomendado
|
1030 |
-
# recommendations_with_prob = []
|
1031 |
-
# if total_similarity > 0: # Verificar que total_similarity no sea cero
|
1032 |
-
# recommendations_with_prob = [(product, score / total_similarity) for product, score in recommendations_count.items()]
|
1033 |
-
# else:
|
1034 |
-
# print("No se encontraron similitudes suficientes para calcular probabilidades.")
|
1035 |
-
|
1036 |
-
# recommendations_with_prob.sort(key=lambda x: x[1], reverse=True) # Ordenar por puntuación
|
1037 |
-
|
1038 |
-
# # Crear un nuevo DataFrame para almacenar las recomendaciones con descripciones y probabilidades
|
1039 |
-
# recommendations_df = pd.DataFrame(columns=['ARTICULO', 'DESCRIPCION', 'PROBABILIDAD'])
|
1040 |
-
|
1041 |
-
# # Agregar las recomendaciones al DataFrame usando pd.concat
|
1042 |
-
# for product, prob in recommendations_with_prob:
|
1043 |
-
# # Buscar la descripción en el DataFrame de productos
|
1044 |
-
# description = productos.loc[productos['ARTICULO'] == product, 'DESCRIPCION']
|
1045 |
-
# if not description.empty:
|
1046 |
-
# # Crear un nuevo DataFrame temporal para la recomendación
|
1047 |
-
# temp_df = pd.DataFrame({
|
1048 |
-
# 'ARTICULO': [product],
|
1049 |
-
# 'DESCRIPCION': [description.values[0]], # Obtener el primer valor encontrado
|
1050 |
-
# 'PROBABILIDAD': [prob]
|
1051 |
-
# })
|
1052 |
-
# # Concatenar el DataFrame temporal al DataFrame de recomendaciones
|
1053 |
-
# recommendations_df = pd.concat([recommendations_df, temp_df], ignore_index=True)
|
1054 |
-
|
1055 |
-
# return recommendations_df
|
1056 |
-
|
1057 |
-
# # Comprobar si el cliente está en el CSV de fieles
|
1058 |
-
# is_fiel = customer_code in fieles_df['Cliente'].astype(str).values
|
1059 |
-
|
1060 |
-
# if customer_code:
|
1061 |
-
# if is_fiel:
|
1062 |
-
# st.write(f"### Customer {customer_code} is a loyal customer.")
|
1063 |
-
# option = st.selectbox("Select Recommendation Type", ["Select an option", "By Purchase History", "By Current Basket"])
|
1064 |
-
|
1065 |
-
# if option == "By Purchase History":
|
1066 |
-
# st.warning("Option not available... aún")
|
1067 |
-
# elif option == "By Current Basket":
|
1068 |
-
# st.write("Select the items and assign quantities for the basket:")
|
1069 |
-
|
1070 |
-
# # Mostrar lista de artículos disponibles
|
1071 |
-
# available_articles = productos['ARTICULO'].unique()
|
1072 |
-
# selected_articles = st.multiselect("Select Articles", available_articles)
|
1073 |
-
|
1074 |
-
# # Crear inputs para ingresar las cantidades de cada artículo seleccionado
|
1075 |
-
# quantities = {}
|
1076 |
-
# for article in selected_articles:
|
1077 |
-
# quantities[article] = st.number_input(f"Quantity for {article}", min_value=0, step=1)
|
1078 |
-
|
1079 |
-
# if st.button("Calcular"): # Añadimos el botón "Calcular"
|
1080 |
-
# # Crear una lista de artículos basada en la selección
|
1081 |
-
# new_basket = [f"{article} x{quantities[article]}" for article in selected_articles if quantities[article] > 0]
|
1082 |
-
|
1083 |
-
# if new_basket:
|
1084 |
-
# # Procesar la lista para recomendar
|
1085 |
-
# recommendations_df = recomienda(new_basket)
|
1086 |
-
|
1087 |
-
# if not recommendations_df.empty:
|
1088 |
-
# st.write("### Recommendations based on the current basket:")
|
1089 |
-
# st.dataframe(recommendations_df)
|
1090 |
-
# else:
|
1091 |
-
# st.warning("No recommendations found for the provided basket.")
|
1092 |
-
# else:
|
1093 |
-
# st.warning("Please select at least one article and set its quantity.")
|
1094 |
# else:
|
1095 |
-
# st.
|
1096 |
-
# st.write("Select items and assign quantities for the basket:")
|
1097 |
-
|
1098 |
-
# # Mostrar lista de artículos disponibles
|
1099 |
-
# available_articles = productos['ARTICULO'].unique()
|
1100 |
-
# selected_articles = st.multiselect("Select Articles", available_articles)
|
1101 |
-
|
1102 |
-
# # Crear inputs para ingresar las cantidades de cada artículo seleccionado
|
1103 |
-
# quantities = {}
|
1104 |
-
# for article in selected_articles:
|
1105 |
-
# quantities[article] = st.number_input(f"Quantity for {article}", min_value=0, step=1)
|
1106 |
-
|
1107 |
-
# if st.button("Calcular"): # Añadimos el botón "Calcular"
|
1108 |
-
# # Crear una lista de artículos basada en la selección
|
1109 |
-
# new_basket = [f"{article} x{quantities[article]}" for article in selected_articles if quantities[article] > 0]
|
1110 |
-
|
1111 |
-
# if new_basket:
|
1112 |
-
# # Procesar la lista para recomendar
|
1113 |
-
# recommendations_df = recomienda(new_basket)
|
1114 |
-
|
1115 |
-
# if not recommendations_df.empty:
|
1116 |
-
# st.write("### Recommendations based on the current basket:")
|
1117 |
-
# st.dataframe(recommendations_df)
|
1118 |
-
# else:
|
1119 |
-
# st.warning("No recommendations found for the provided basket.")
|
1120 |
-
# else:
|
1121 |
-
# st.warning("Please select at least one article and set its quantity.")
|
1122 |
-
|
|
|
680 |
else:
|
681 |
st.warning(f"No predicted or actual data found for customer {customer_code} for 2024.")
|
682 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
683 |
# Customer Recommendations Page
|
684 |
elif page == "Articles Recommendations":
|
685 |
+
# Estilo principal de la página
|
686 |
+
st.markdown(
|
687 |
+
"<h1 style='text-align: center; color: #2E86C1;'>Articles Recommendations</h1>",
|
688 |
+
unsafe_allow_html=True
|
689 |
+
)
|
690 |
st.markdown("""
|
691 |
+
<p style='text-align: center; color: #5D6D7E;'>Get tailored recommendations for your customers based on their basket.</p>
|
692 |
+
""", unsafe_allow_html=True)
|
693 |
+
st.write("### Select items and assign quantities for the basket:")
|
694 |
+
# Añadir separador para mejorar la segmentación visual
|
695 |
+
st.divider()
|
696 |
# Mostrar lista de artículos disponibles
|
697 |
+
available_articles = productos['DESCRIPCION'].unique()
|
698 |
selected_articles = st.multiselect("Select Articles", available_articles)
|
699 |
+
# Mostrar cantidades en la misma fila
|
700 |
quantities = {}
|
701 |
+
if selected_articles:
|
702 |
+
st.write("### Selected Items and Quantities:")
|
703 |
+
for article in selected_articles:
|
704 |
+
col1, col2 = st.columns([3, 1]) # Configurar las proporciones de las columnas
|
705 |
+
with col1:
|
706 |
+
st.write(article) # Mostrar el nombre del artículo
|
707 |
+
with col2:
|
708 |
+
quantities[article] = st.number_input(f"Qty for {article}", min_value=0, step=1, key=article) # Pedir cantidad
|
709 |
+
# Añadir un botón estilizado "Calcular" con icono
|
710 |
+
if st.button("🛒 Calculate Recommendations"):
|
711 |
# Crear una lista de artículos basada en la selección de códigos y cantidades
|
712 |
new_basket = []
|
713 |
for article in selected_articles:
|
|
|
717 |
if new_basket:
|
718 |
# Procesar la lista para recomendar
|
719 |
recommendations_df = recomienda_tfid(new_basket)
|
720 |
+
|
721 |
if not recommendations_df.empty:
|
722 |
+
st.success("### Recommendations based on the current basket:")
|
723 |
+
st.dataframe(recommendations_df, height=300, width=800) # Ajustar el tamaño del DataFrame
|
724 |
else:
|
725 |
+
st.warning("⚠️ No recommendations found for the provided basket.")
|
726 |
else:
|
727 |
+
st.warning("⚠️ Please select at least one article and set its quantity.")
|
728 |
|
729 |
# # Customer Recommendations Page
|
730 |
# elif page == "Articles Recommendations":
|
731 |
# st.title("Articles Recommendations")
|
|
|
732 |
# st.markdown("""
|
733 |
# Get tailored recommendations for your customers based on their basket.
|
734 |
# """)
|
735 |
+
# st.write("Select items and assign quantities for the basket:")
|
736 |
+
# # Mostrar lista de artículos disponibles
|
737 |
+
# available_articles = productos['ARTICULO'].unique()
|
738 |
+
# selected_articles = st.multiselect("Select Articles", available_articles)
|
739 |
+
# # Crear inputs para ingresar las cantidades de cada artículo seleccionado
|
740 |
+
# quantities = {}
|
741 |
+
# for article in selected_articles:
|
742 |
+
# quantities[article] = st.number_input(f"Quantity for {article}", min_value=0, step=1)
|
743 |
+
# if st.button("Calcular"): # Añadimos el botón "Calcular"
|
744 |
+
# # Crear una lista de artículos basada en la selección de códigos y cantidades
|
745 |
+
# new_basket = []
|
746 |
+
# for article in selected_articles:
|
747 |
+
# quantity = quantities[article]
|
748 |
+
# if quantity > 0:
|
749 |
+
# new_basket.extend([article] * quantity) # Añadir el código 'article' tantas veces como 'quantity'
|
750 |
+
# if new_basket:
|
751 |
+
# # Procesar la lista para recomendar
|
752 |
+
# recommendations_df = recomienda_tfid(new_basket)
|
753 |
+
# if not recommendations_df.empty:
|
754 |
+
# st.write("### Recommendations based on the current basket:")
|
755 |
+
# st.dataframe(recommendations_df)
|
756 |
+
# else:
|
757 |
+
# st.warning("No recommendations found for the provided basket.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
758 |
# else:
|
759 |
+
# st.warning("Please select at least one article and set its quantity.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|