Spaces:
Sleeping
Sleeping
File size: 7,182 Bytes
7a703ad e914943 7a703ad e914943 1f115ec e914943 959f7ba e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad d3438ea e914943 7a703ad d3438ea 7a703ad e914943 7a703ad e914943 7a703ad 959f7ba 7a703ad e914943 d3438ea 7a703ad e914943 7a703ad e914943 7a703ad e914943 a01ffab e914943 7a703ad e914943 959f7ba 7a703ad e914943 7a703ad 959f7ba 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad e914943 7a703ad d3438ea |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
import gradio as gr
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
# =========================================================
# 1. CARREGAMENTO E LIMPEZA DE DADOS
# =========================================================
def load_data():
# --- SIMULAÇÃO DE DADOS ---
# Se estiver usando seu arquivo real, descomente a linha abaixo:
# df = pd.read_csv("seu_ficheiro.csv", sep=";")
data = {
'Marca': ['VALTRA', 'KIOTI', 'JOHN DEERE', 'NEW HOLLAND', 'KUBOTA', 'VALTRA', 'KIOTI', 'SOLIS', 'FENDT', 'CLAAS'] * 50,
'Regiao': ['Norte', 'Centro', 'Alentejo', 'Norte', 'Algarve'] * 100,
'Tipo': ['="Agricola"'] * 500,
'Potencia kW': ['="75"', '="19"', '="88"', '="55"', '="70"', '="121"', '="44"', '="19"', '="176"', '="90"'] * 50,
}
df = pd.DataFrame(data)
# ----------------------------------------------------------
# === SUA LIMPEZA ===
# 1. Limpar Tipo
df['Tipo_clean'] = df['Tipo'].astype(str).str.replace('="', '', regex=False).str.replace('"', '', regex=False).str.strip().str.upper()
df = df[df['Tipo_clean'] == 'AGRICOLA'].copy()
# 2. Limpar Potência
df["Potencia kW"] = df["Potencia kW"].astype(str).str.replace(r'[="]', '', regex=True)
df["Potencia kW"] = pd.to_numeric(df["Potencia kW"], errors='coerce')
df = df.dropna(subset=["Potencia kW"])
# 3. Criar Segmentos
bins = [0, 25, 50, 100, 500]
labels = ['< 25 kW (Compactos)', '25 - 50 kW', '50 - 100 kW', '> 100 kW (Alta)']
df['Cluster Potencia'] = pd.cut(df['Potencia kW'], bins=bins, labels=labels)
df['Cluster Potencia'] = df['Cluster Potencia'].astype(str)
return df
# Carregar dados globais
df_global = load_data()
min_kw_global = int(df_global["Potencia kW"].min())
max_kw_global = int(df_global["Potencia kW"].max())
all_regions = sorted(df_global["Regiao"].unique().tolist())
# =========================================================
# 2. LÓGICA DO DASHBOARD
# =========================================================
def update_dashboard(val_min, val_max, selected_regions):
# Garantir que min não é maior que max
if val_min > val_max:
val_min, val_max = val_max, val_min
# 1. Filtrar DataFrame
mask = (
(df_global["Potencia kW"] >= val_min) &
(df_global["Potencia kW"] <= val_max) &
(df_global["Regiao"].isin(selected_regions))
)
df_filtered = df_global[mask]
if df_filtered.empty:
return "0", "0%", "0%", None, None, None, pd.DataFrame()
# 2. KPIs
total = len(df_filtered)
v_valtra = len(df_filtered[df_filtered['Marca'].str.upper() == 'VALTRA'])
v_kioti = len(df_filtered[df_filtered['Marca'].str.upper() == 'KIOTI'])
# Evitar erro de divisão por zero
share_valtra = (v_valtra / total * 100) if total > 0 else 0
share_kioti = (v_kioti / total * 100) if total > 0 else 0
kpi_total_txt = f"{total} Unidades"
kpi_valtra_txt = f"{share_valtra:.1f}% ({v_valtra})"
kpi_kioti_txt = f"{share_kioti:.1f}% ({v_kioti})"
# 3. Gráfico Ranking (Cores Inteligentes)
top_marcas = df_filtered['Marca'].value_counts().reset_index().head(15)
top_marcas.columns = ['Marca', 'Vendas']
colors = []
for marca in top_marcas['Marca']:
if marca.upper() == 'VALTRA': colors.append('#d62728') # Vermelho
elif marca.upper() == 'KIOTI': colors.append('#ff7f0e') # Laranja
else: colors.append('#cccccc') # Cinza
fig_rank = go.Figure(data=[go.Bar(
x=top_marcas['Marca'], y=top_marcas['Vendas'],
marker_color=colors, text=top_marcas['Vendas'], textposition='auto'
)])
fig_rank.update_layout(title="Ranking de Mercado (Top 15)", template="plotly_white", height=400)
# 4. Gráfico Potência
vendas_cluster = df_filtered['Cluster Potencia'].value_counts().reset_index()
vendas_cluster.columns = ['Cluster', 'Vendas']
fig_pie = px.pie(vendas_cluster, values='Vendas', names='Cluster',
title='Distribuição por Potência', hole=0.4)
# 5. Gráfico Segmentos
nossas = df_filtered[df_filtered['Marca'].isin(['VALTRA', 'KIOTI'])]
if not nossas.empty:
fig_seg = px.histogram(nossas, x="Cluster Potencia", color="Marca",
barmode="group", title="Posicionamento: Valtra vs Kioti",
color_discrete_map={'VALTRA': '#d62728', 'KIOTI': '#ff7f0e'})
else:
fig_seg = go.Figure().add_annotation(text="Sem dados Valtra/Kioti", showarrow=False)
return kpi_total_txt, kpi_valtra_txt, kpi_kioti_txt, fig_rank, fig_pie, fig_seg, df_filtered
# =========================================================
# 3. INTERFACE GRADIO
# =========================================================
with gr.Blocks(title="Dashboard Executivo", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🚜 Dashboard de Mercado: Valtra & KIOTI")
gr.Markdown("_Visão estratégica para Direção Geral_")
with gr.Row():
# --- COLUNA DE FILTROS ---
with gr.Column(scale=1):
gr.Label("⚙️ Filtros")
# SUBSTITUIÇÃO DO RANGESLIDER POR DOIS SLIDERS SIMPLES
slider_min = gr.Slider(minimum=min_kw_global, maximum=max_kw_global, value=min_kw_global, step=1, label="Potência Mínima (kW)")
slider_max = gr.Slider(minimum=min_kw_global, maximum=max_kw_global, value=max_kw_global, step=1, label="Potência Máxima (kW)")
chk_region = gr.CheckboxGroup(choices=all_regions, value=all_regions, label="Regiões")
btn_refresh = gr.Button("Atualizar Dados", variant="primary")
# --- COLUNA DOS GRÁFICOS ---
with gr.Column(scale=3):
with gr.Row():
kpi_total = gr.Text(label="Mercado Total (Filtro)")
kpi_valtra = gr.Text(label="Share VALTRA")
kpi_kioti = gr.Text(label="Share KIOTI")
gr.Markdown("### 🏆 Performance de Mercado")
plot_ranking = gr.Plot(label="Ranking de Vendas")
with gr.Row():
plot_potencia = gr.Plot(label="Mix de Potência")
plot_segmento = gr.Plot(label="Nossas Marcas por Segmento")
with gr.Accordion("📂 Ver Dados Detalhados", open=False):
data_table = gr.Dataframe(headers=list(df_global.columns))
# =========================================================
# 4. LIGAÇÕES (WIRING)
# =========================================================
inputs = [slider_min, slider_max, chk_region]
outputs = [kpi_total, kpi_valtra, kpi_kioti, plot_ranking, plot_potencia, plot_segmento, data_table]
slider_min.change(fn=update_dashboard, inputs=inputs, outputs=outputs)
slider_max.change(fn=update_dashboard, inputs=inputs, outputs=outputs)
chk_region.change(fn=update_dashboard, inputs=inputs, outputs=outputs)
btn_refresh.click(fn=update_dashboard, inputs=inputs, outputs=outputs)
demo.load(fn=update_dashboard, inputs=inputs, outputs=outputs)
if __name__ == "__main__":
demo.launch() |