File size: 7,680 Bytes
ef6d407 |
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 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
from typing import Dict, Optional, List
# Definindo as 5 categorias CIF fixas e a ordem desejada
FIXED_ICF_COMPONENT_LABELS: List[str] = [
'Funções Corporais (b)',
'Atividades e Participação (d)',
'Ambiente (e)',
'Estruturas Corporais (s)',
'Outros'
]
# Mapeamento fixo de cores para cada categoria
ICF_COMPONENT_COLOR_MAP: Dict[str, str] = {
'Funções Corporais (b)': '#FFC145', # Amarelo/Laranja
'Atividades e Participação (d)': '#B7F242', # Verde claro
'Ambiente (e)': '#4369C0', # Azul
'Estruturas Corporais (s)': '#DA3B95', # Rosa/Roxo
'Outros': '#AAAAAA' # Cinza
}
def create_pie_chart(
input_df: pd.DataFrame,
title: str = "Distribuição da Classificação"
) -> Optional[go.Figure]:
"""
Generates a pie chart from a DataFrame, using consistent colors for ICF categories
present in the input data.
Args:
input_df (pd.DataFrame): DataFrame with 'Componente CIF' (labels)
and 'Frequencia' (values) columns.
title (str): The title of the chart.
Returns:
Optional[go.Figure]: The Plotly Figure object containing the pie chart,
or None if there is no valid data to plot (e.g., all frequencies are zero or negative).
"""
# Verificar se o DataFrame de entrada está vazio
# Check if the input DataFrame is empty
if input_df.empty:
print(f"Aviso: DataFrame de entrada para o gráfico de pizza '{title}' está vazio. Retornando None.")
return None
# Filtrar categorias com frequência zero ou negativa, pois não aparecem no gráfico de pizza
# Filter out categories with zero or negative frequency, as they don't appear in a pie chart
plot_df = input_df[input_df['Frequencia'] > 0].copy()
# Verificar se há dados válidos para plotar após a filtragem
# Check if there's any valid data to plot after filtering
if plot_df.empty:
print(f"Aviso: Nenhum dado com frequência positiva para gerar o gráfico de pizza: '{title}'. Retornando None.")
return None
# Garantir a ordem das categorias no gráfico e na legenda para as categorias presentes
# Ensure the order of categories in the chart and legend for present categories
category_order_map = {'Componente CIF': FIXED_ICF_COMPONENT_LABELS}
figure = px.pie(
plot_df,
names='Componente CIF',
values='Frequencia',
title=title,
color='Componente CIF',
color_discrete_map=ICF_COMPONENT_COLOR_MAP, # Usar o mapeamento fixo de cores
category_orders=category_order_map # Forçar a ordem para categorias presentes
)
figure.update_layout(legend_title_text='Componentes')
figure.update_traces(
direction='clockwise',
rotation=-30, # Rotação inicial das fatias
textinfo="label+value+percent",
textposition='outside',
textfont_size=16,
pull=0.05, # Destaca ligeiramente as fatias
hovertemplate="<b>%{label}</b><br>Frequência: %{value}<br>Porcentagem: %{percent}<extra></extra>"
)
return figure
def create_bar_chart(
input_df: pd.DataFrame,
title: str = "Frequência da Classificação"
) -> Optional[go.Figure]:
"""
Generates a bar chart from a DataFrame, using consistent colors for ICF categories
present in the input data.
Args:
input_df (pd.DataFrame): DataFrame with 'Componente CIF' (X-axis)
and 'Frequencia' (Y-axis) columns.
title (str): The title of the chart.
Returns:
Optional[go.Figure]: The Plotly Figure object containing the bar chart,
or None if there is no valid data to plot (e.g., all frequencies are zero).
"""
# Verificar se o DataFrame de entrada está vazio
# Check if the input DataFrame is empty
if input_df.empty:
print(f"Aviso: DataFrame de entrada para o gráfico de barras '{title}' está vazio. Retornando None.")
return None
# Verificar se todas as frequências são zero (ou menores)
# Check if all frequencies are zero (or less)
# Embora frequências devam ser não-negativas, somar pode ser problemático se houver NaNs.
# A simple check for non-positive sum is robust if data is clean.
# If 'Frequencia' can have NaN, they should be handled (e.g., fillna(0) or dropna())
# For simplicity, assuming 'Frequencia' is numeric and NaNs are not the primary concern here.
# A more robust check for "no positive data" might be (input_df['Frequencia'] <= 0).all()
# but sum() == 0 is what was implicitly checked before with merged_df.
if input_df['Frequencia'].sum() == 0: # Assuming frequencies are non-negative
print(f"Aviso: Todos os dados em input_df têm frequência 0 para o gráfico de barras: '{title}'. Retornando None.")
return None
# Garantir a ordem das categorias no gráfico para as categorias presentes
# Ensure the order of categories in the chart for present categories
category_order_map = {'Componente CIF': FIXED_ICF_COMPONENT_LABELS}
figure = px.bar(
input_df, # Usar o DataFrame de entrada diretamente
x='Componente CIF',
y='Frequencia',
title=title,
labels={'Componente CIF': 'Componentes CIF', 'Frequencia': 'Frequência'},
color='Componente CIF',
color_discrete_map=ICF_COMPONENT_COLOR_MAP, # Usar o mapeamento fixo de cores
category_orders=category_order_map, # Forçar a ordem para categorias presentes
text_auto=True # Exibe o valor da frequência em cima da barra automaticamente
)
figure.update_layout(
legend_title_text='Componentes',
xaxis_title="Componentes CIF",
yaxis_title="Frequência",
showlegend=True # Garante que a legenda seja mostrada
)
figure.update_traces(
textfont_size=14,
textangle=0,
textposition="inside", # Posição do texto da frequência (pode ser 'inside' ou 'outside')
hovertemplate="<b>%{x}</b><br>Frequência: %{y}<extra></extra>"
)
return figure
def create_tree_map_chart(
tree_map_df: pd.DataFrame,
title: str = "Treemap de Frequências por Hierarquia de Códigos"
) -> Optional[go.Figure]:
"""
Generates a Treemap chart from a DataFrame.
Args:
tree_map_df (pd.DataFrame): DataFrame with 'Parent', 'Subparent',
'Filho' (Child), and 'Frequencia' (Frequency) columns.
title (str): The title of the chart.
Returns:
Optional[go.Figure]: The Plotly Figure object containing the Treemap chart,
or None if the DataFrame is empty.
"""
if tree_map_df.empty:
print(f"Aviso: DataFrame vazio para gerar o Treemap: '{title}'.")
return None
figure = px.treemap(
tree_map_df,
path=['Parent', 'Subparent', 'Filho'], # Define a hierarquia
values='Frequencia', # Define os valores que determinam o tamanho dos retângulos
title=title,
color='Frequencia', # Colore os retângulos com base na frequência
color_continuous_scale='spectral_r', # Esquema de cores
height=700, # Altura do gráfico
)
figure.update_traces(
textinfo="label+value+percent entry", # Informações exibidas em cada retângulo
hovertemplate='<b>%{label}</b><br>Frequência: %{value}<br>Porcentagem: %{percentEntry:.1%}<extra></extra>',
)
return figure
|