import streamlit as st import pandas as pd import plotly.express as px import matplotlib.pyplot as plt import numpy as np # Page configuration st.set_page_config(page_title="Customer Insights App", page_icon=":bar_chart:") # Load CSV files df = pd.read_csv("df_clean.csv") nombres_proveedores = pd.read_csv("nombres_proveedores.csv", sep=';') euros_proveedor = pd.read_csv("euros_proveedor.csv", sep=',') nombres_proveedores['codigo'] = nombres_proveedores['codigo'].astype(str) euros_proveedor['CLIENTE'] = euros_proveedor['CLIENTE'].astype(str) # Ignore the last two columns df = df.iloc[:, :-2] # Ensure customer code is a string df['CLIENTE'] = df['CLIENTE'].astype(str) # Function to get supplier name def get_supplier_name(code): name = nombres_proveedores[nombres_proveedores['codigo'] == code]['nombre'].values return name[0] if len(name) > 0 else code # Function to create radar chart with square root transformation def radar_chart(categories, values, amounts, title): N = len(categories) angles = [n / float(N) * 2 * np.pi for n in range(N)] angles += angles[:1] fig, ax = plt.subplots(figsize=(12, 12), subplot_kw=dict(projection='polar')) # Apply square root transformation sqrt_values = np.sqrt(values) sqrt_amounts = np.sqrt(amounts) max_sqrt_value = max(sqrt_values) normalized_values = [v / max_sqrt_value for v in sqrt_values] total_sqrt_amount = sum(sqrt_amounts) normalized_amounts = [a / total_sqrt_amount for a in sqrt_amounts] normalized_values += normalized_values[:1] ax.plot(angles, normalized_values, 'o-', linewidth=2, color='#FF69B4', label='% Units (sqrt)') ax.fill(angles, normalized_values, alpha=0.25, color='#FF69B4') normalized_amounts += normalized_amounts[:1] ax.plot(angles, normalized_amounts, 'o-', linewidth=2, color='#4B0082', label='% Spend (sqrt)') ax.fill(angles, normalized_amounts, alpha=0.25, color='#4B0082') ax.set_xticks(angles[:-1]) ax.set_xticklabels(categories, size=8, wrap=True) ax.set_ylim(0, max(max(normalized_values), max(normalized_amounts)) * 1.1) circles = np.linspace(0, 1, 5) for circle in circles: ax.plot(angles, [circle]*len(angles), '--', color='gray', alpha=0.3, linewidth=0.5) ax.set_yticklabels([]) ax.spines['polar'].set_visible(False) plt.title(title, size=16, y=1.1) plt.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1)) return fig # Main page design st.title("Welcome to Customer Insights App") st.markdown(""" This app helps businesses analyze customer behaviors and provide personalized recommendations based on purchase history. Use the tools below to dive deeper into your customer data. """) # Navigation menu page = st.selectbox("Select the tool you want to use", ["", "Customer Analysis", "Customer Recommendations"]) # Home Page if page == "": st.markdown("## Welcome to the Customer Insights App") st.write("Use the dropdown menu to navigate between the different sections.") # Customer Analysis Page elif page == "Customer Analysis": st.title("Customer Analysis") st.markdown("Use the tools below to explore your customer data.") partial_code = st.text_input("Enter part of Customer Code (or leave empty to see all)") if partial_code: filtered_customers = df[df['CLIENTE'].str.contains(partial_code)] else: filtered_customers = df customer_list = filtered_customers['CLIENTE'].unique() customer_code = st.selectbox("Select Customer Code", customer_list) if customer_code: customer_data = df[df["CLIENTE"] == customer_code] customer_euros = euros_proveedor[euros_proveedor["CLIENTE"] == customer_code] if not customer_data.empty and not customer_euros.empty: st.write(f"### Analysis for Customer {customer_code}") all_manufacturers = customer_data.iloc[:, 1:].T[customer_data.iloc[:, 1:].T[customer_data.index[0]] > 0] # Convert to numeric and handle any non-numeric values all_manufacturers = all_manufacturers.apply(pd.to_numeric, errors='coerce') customer_euros = customer_euros.apply(pd.to_numeric, errors='coerce') top_units = all_manufacturers.sort_values(by=customer_data.index[0], ascending=False).head(10) # Ensure we're working with numeric data for sorting numeric_euros = customer_euros.select_dtypes(include=[np.number]) if not numeric_euros.empty: top_sales = numeric_euros.iloc[0].sort_values(ascending=False).head(10) else: st.warning("No numeric sales data available for this customer.") top_sales = pd.Series() combined_top = pd.concat([top_units, top_sales]).index.unique() values = [] manufacturers = [] amounts = [] for m in combined_top: if m in all_manufacturers.index: values.append(all_manufacturers[m]) manufacturers.append(get_supplier_name(m)) amounts.append(customer_euros[m].values[0] if m in customer_euros.columns else 0) st.write(f"### Results for top {len(manufacturers)} manufacturers (balanced by units and sales):") for manufacturer, value, amount in zip(manufacturers, values, amounts): st.write(f"{manufacturer} = {value:.4f} units, €{amount:.2f}") if manufacturers: # Only create the chart if we have data fig = radar_chart(manufacturers, values, amounts, f'Radar Chart for Top {len(manufacturers)} Manufacturers of Customer {customer_code}') st.pyplot(fig) else: st.warning("No data available to create the radar chart.") # Customer sales 2021-2024 (if data exists) if 'VENTA_2021' in df.columns and 'VENTA_2022' in df.columns and 'VENTA_2023' in df.columns and 'VENTA_2024' in df.columns: years = ['2021', '2022', '2023', '2024'] sales_columns = ['VENTA_2021', 'VENTA_2022', 'VENTA_2023', 'VENTA_2024'] customer_sales = customer_data[sales_columns].values[0] fig_sales = px.line(x=years, y=customer_sales, markers=True, title=f'Sales Over the Years for Customer {customer_code}') fig_sales.update_layout(xaxis_title="Year", yaxis_title="Sales") st.plotly_chart(fig_sales) else: st.warning("Sales data for 2021-2024 not available.") else: st.warning(f"No data found for customer {customer_code}. Please check the code.") # Customer Recommendations Page elif page == "Customer Recommendations": st.title("Customer Recommendations") st.markdown(""" Get tailored recommendations for your customers based on their purchasing history. """) partial_code = st.text_input("Enter part of Customer Code for Recommendations (or leave empty to see all)") if partial_code: filtered_customers = df[df['CLIENTE'].str.contains(partial_code)] else: filtered_customers = df customer_list = filtered_customers['CLIENTE'].unique() customer_code = st.selectbox("Select Customer Code for Recommendations", customer_list) if customer_code: customer_data = df[df["CLIENTE"] == customer_code] if not customer_data.empty: st.write(f"### Purchase History for Customer {customer_code}") st.write(customer_data) st.write(f"### Recommended Products for Customer {customer_code}") # Placeholder for recommendation logic st.write("Product A, Product B, Product C") else: st.warning(f"No data found for customer {customer_code}. Please check the code.")