005 ‐ Unsupervised Machine Learning Análise de Correspondência Simples e Múltipla - NaimeAndere/Study-Area GitHub Wiki
Unsupervised Machine Learning Análise de Correspondência Simples e Múltipla
Análise de Correspondência Simples (ACS)
Definição: A Análise de Correspondência Simples (ACS) é uma técnica estatística multivariada usada para analisar e visualizar a relação entre duas variáveis categóricas. Ela permite transformar uma tabela de contingência (ou tabela de frequência) em um mapa perceptual, onde linhas e colunas da tabela são representadas como pontos em um espaço multidimensional.
Objetivos:
- Identificar e interpretar as relações entre categorias das duas variáveis.
- Reduzir a dimensionalidade dos dados, facilitando a visualização e interpretação.
Etapas da ACS:
- Construção da Tabela de Contingência: Uma tabela de contingência é criada com as frequências observadas das combinações das categorias das duas variáveis.
- Cálculo das Proporções: Calculam-se as proporções relativas das frequências.
- Matriz de Perfis: Criação de perfis das linhas e colunas a partir das proporções.
- Centros de Massa: Determinação dos centros de massa das linhas e colunas.
- Análise dos Componentes Principais: Decomposição da matriz para obter os componentes principais que explicam a maior parte da variação nos dados.
- Plotagem: Representação gráfica das categorias como pontos em um gráfico bidimensional ou tridimensional, onde a proximidade dos pontos indica a similaridade entre as categorias.
Aplicações:
- Pesquisa de mercado para analisar preferências dos consumidores.
- Análise de dados demográficos.
- Estudos de ciências sociais para entender relações entre variáveis categóricas.
Análise de Correspondência Múltipla (ACM)
Definição: A Análise de Correspondência Múltipla (ACM) é uma extensão da Análise de Correspondência Simples que permite analisar e visualizar relações entre mais de duas variáveis categóricas. É especialmente útil para grandes conjuntos de dados categóricos.
Objetivos:
- Identificar padrões de associação entre múltiplas variáveis categóricas.
- Reduzir a dimensionalidade dos dados para facilitar a interpretação.
- Visualizar as relações complexas entre variáveis em um espaço de menor dimensão.
Etapas da ACM:
- Construção da Tabela de Dados: Uma tabela de dados é construída com várias variáveis categóricas.
- Conversão em Indicadoras: Cada categoria de cada variável é convertida em variáveis indicadoras (dummy variables).
- Matriz de Perfis: Criação de perfis das linhas e colunas a partir das variáveis indicadoras.
- Centros de Massa: Determinação dos centros de massa das linhas e colunas.
- Análise dos Componentes Principais: Decomposição da matriz para obter os componentes principais que explicam a maior parte da variação nos dados.
- Plotagem: Representação gráfica das categorias e observações como pontos em um gráfico multidimensional, onde a proximidade dos pontos indica similaridade.
Aplicações:
- Análise de questionários de pesquisa com múltiplas perguntas categóricas.
- Segmentação de mercado.
- Estudos epidemiológicos para entender fatores de risco associados a doenças.
- Análise de dados comportamentais.
Exemplo Prático
ACS: Imagine que uma pesquisa foi realizada para entender a relação entre o gênero (masculino e feminino) e a preferência por três tipos de frutas (maçã, banana, laranja). A ACS pode ser usada para visualizar como as preferências de frutas variam entre homens e mulheres.
ACM: Suponha que uma pesquisa de satisfação do cliente inclui várias perguntas categóricas sobre a qualidade do serviço, atendimento ao cliente, e preço. A ACM pode ser utilizada para identificar padrões de associação entre essas múltiplas variáveis e visualizá-los em um gráfico multidimensional.
Ambas as técnicas são poderosas para explorar e entender relações complexas em dados categóricos, facilitando a tomada de decisões baseadas em dados.
Procedimentos e Exemplos para Análise de Correspondência Simples
Módulos Utilizados
#%% Instalando os pacotes
! pip install pandas
! pip install numpy
! pip install scipy
! pip install plotly
! pip install seaborn
! pip install matplotlib
! pip install statsmodels
! pip install prince
#%% Importando os pacotes necessários
import pandas as pd
import numpy as np
from scipy.stats import chi2_contingency
import statsmodels.api as sm
import seaborn as sns
import matplotlib.pyplot as plt
import prince
import plotly.io as pio
pio.renderers.default = 'browser'
import plotly.graph_objects as go
[perfil_aplicacao.xlsx](https://prod-files-secure.s3.us-west-2.amazonaws.com/ed5c9723-2c6b-4e68-9eef-26f3e75b8625/c24fd228-e048-42a9-9064-a6ee9c204a5e/perfil_aplicacao.xlsx)
Importação dos dados
perfil = pd.read_excel("perfil_aplicacao.xlsx")

Informações descritivas sobre as variáveis
print(perfil['Perfil'].value_counts())
print(perfil['Tipo de Aplicação'].value_counts())

Criando a tabela de contingência
Tabela = pd.crosstab(perfil["Perfil"], perfil["Tipo de Aplicação"])

Analisando a significância estatística da associação (teste qui²)
teste_qui2 = chi2_contingency(tabela)
print(f"estatística qui²: {round(teste_qui2[0], 2)}")
print(f"p-valor da estatística: {round(teste_qui2[1], 4)}")
print(f"graus de liberdade: {teste_qui2[2]}")

Análise dos resíduos provenientes da tabela de contingência
# Parametrizando a função
tab_cont = sm.stats.Table(tabela)
# Tabela de frequências absolutas esperadas
print(tab_cont.fittedvalues)
# Tabela de resíduos: diferença entre freq. absolutas observadas e esperadas
print(tabela - tab_cont.fittedvalues)
# Valores qui-quadrado por célula
print(tab_cont.chi2_contribs)
# Resíduos padronizados
print(tab_cont.resid_pearson)
# Resíduos padronizados ajustados
print(tab_cont.standardized_resids)

Mapa de calor dos resíduos padronizados ajustados
fig = go.Figure()
maxz = np.max(tab_cont.standardized_resids)+0.1
minz = np.min(tab_cont.standardized_resids)-0.1
colorscale = ['skyblue' if i>1.96 else '#FAF9F6' for i in np.arange(minz,maxz,0.01)]
fig.add_trace(
go.Heatmap(
x = tab_cont.standardized_resids.columns,
y = tab_cont.standardized_resids.index,
z = np.array(tab_cont.standardized_resids),
text=tab_cont.standardized_resids.values,
texttemplate='%{text:.2f}',
showscale=False,
colorscale=colorscale))
fig.update_layout(
title='Resíduos Padronizados Ajustados',
height = 600,
width = 600)
fig.show()
Elaborando a ANACOR
# Na função, o input é a tabela de contingência criada antes!
ca = prince.CA().fit(tabela)
Obtendo os eigenvalues
tabela_autovalores = ca.eigenvalues_summary
print(tabela_autovalores)
# São gerados 'm' autovalores: m = mín(I-1,J-1)
Obtendo a inércia principal total
# É a soma dos eigenvalues (também é a divisão: estat. qui² / N)
# Quanto maior a inércia principal total, maior é a associação entre categorias
print(ca.total_inertia_)
Massas das categorias
# Massas da variável em linha
print(ca.row_masses_)
# Massas da variável em coluna
print(ca.col_masses_)
Autovetores
# Massas da variável em linha
print(ca.row_masses_)
# Massas da variável em coluna
print(ca.col_masses_)
Obtendo as coordenadas do mapa perceptual
# Coordenadas da variável em linha
print(ca.row_coordinates(tabela))
# Coordenadas da variável em coluna
print(ca.column_coordinates(tabela))
Plotando o mapa percentual da Anacor
chart_df_row = pd.DataFrame({'var_row': tabela.index,
'x_row':ca.row_coordinates(tabela)[0].values,
'y_row': ca.row_coordinates(tabela)[1].values})
chart_df_col = pd.DataFrame({'var_col': tabela.columns,
'x_col':ca.column_coordinates(tabela)[0].values,
'y_col': ca.column_coordinates(tabela)[1].values})
def label_point(x, y, val, ax):
a = pd.concat({'x': x, 'y': y, 'val': val}, axis=1)
for i, point in a.iterrows():
ax.text(point['x'] + 0.03, point['y'] - 0.02, point['val'], fontsize=6)
label_point(x = chart_df_col['x_col'],
y = chart_df_col['y_col'],
val = chart_df_col['var_col'],
ax = plt.gca())
label_point(x = chart_df_row['x_row'],
y = chart_df_row['y_row'],
val = chart_df_row['var_row'],
ax = plt.gca())
sns.scatterplot(data=chart_df_row, x='x_row', y='y_row', s=20)
sns.scatterplot(data=chart_df_col, x='x_col', y='y_col', s=20)
sns.despine(top=True, right=True, left=False, bottom=False)
plt.axhline(y=0, color='lightgrey', ls='--')
plt.axvline(x=0, color='lightgrey', ls='--')
plt.tick_params(size=2, labelsize=6)
plt.title("Mapa Perceptual - Anacor", fontsize=12)
plt.xlabel(f"Dim. 1: {tabela_autovalores.iloc[0,1]} da inércia", fontsize=8)
plt.ylabel(f"Dim. 2: {tabela_autovalores.iloc[1,1]} da inércia", fontsize=8)
plt.show()
Obtendo as coordenadas das observações
# Identificando as variáveis em linha e em coluna
coord_obs = perfil.rename(columns={'Perfil':'var_row',
'Tipo de Aplicação':'var_col'})
# Unindo as coordenadas das categorias ao DataFrame
coord_obs = pd.merge(coord_obs, chart_df_row, how='left', on='var_row')
coord_obs = pd.merge(coord_obs, chart_df_col, how='left', on='var_col')
# Calculando as coordenadas médias das observações (média de suas categorias)
coord_obs['x_obs'] = coord_obs['x_row','x_col'](/NaimeAndere/Study-Area/wiki/'x_row','x_col').mean(axis=1)
coord_obs['y_obs'] = coord_obs['y_row','y_col'](/NaimeAndere/Study-Area/wiki/'y_row','y_col').mean(axis=1)
Plotando o mapa percentual da Anacor
chart_df_row = pd.DataFrame({'var_row': tabela.index,
'x_row':ca.row_coordinates(tabela)[0].values,
'y_row': ca.row_coordinates(tabela)[1].values})
chart_df_col = pd.DataFrame({'var_col': tabela.columns,
'x_col':ca.column_coordinates(tabela)[0].values,
'y_col': ca.column_coordinates(tabela)[1].values})
def label_point(x, y, val, ax):
a = pd.concat({'x': x, 'y': y, 'val': val}, axis=1)
for i, point in a.iterrows():
ax.text(point['x'] + 0.03, point['y'] - 0.02, point['val'], fontsize=6)
label_point(x = chart_df_col['x_col'],
y = chart_df_col['y_col'],
val = chart_df_col['var_col'],
ax = plt.gca())
label_point(x = chart_df_row['x_row'],
y = chart_df_row['y_row'],
val = chart_df_row['var_row'],
ax = plt.gca())
sns.scatterplot(data=chart_df_row, x='x_row', y='y_row', s=20)
sns.scatterplot(data=chart_df_col, x='x_col', y='y_col', s=20)
sns.scatterplot(data=coord_obs, x='x_obs', y='y_obs', s=10, color='red')
sns.despine(top=True, right=True, left=False, bottom=False)
plt.axhline(y=0, color='lightgrey', ls='--')
plt.axvline(x=0, color='lightgrey', ls='--')
plt.tick_params(size=2, labelsize=6)
plt.title("Mapa Perceptual - Anacor", fontsize=12)
plt.xlabel(f"Dim. 1: {tabela_autovalores.iloc[0,1]} da inércia", fontsize=8)
plt.ylabel(f"Dim. 2: {tabela_autovalores.iloc[1,1]} da inércia", fontsize=8)
plt.show()
Procedimentos e Exemplos para Análise de Correspondência Múltiplas
Exemplo 1 - Perfil de Aplicação (Estado Civil)
Módulos utilizados
#%% Instalando os pacotes
! pip install pandas
! pip install numpy
! pip install scipy
! pip install plotly
! pip install seaborn
! pip install matplotlib
! pip install statsmodels
! pip install prince
#%% Importando os pacotes necessários
import pandas as pd
import numpy as np
from scipy.stats import chi2_contingency
import statsmodels.api as sm
import seaborn as sns
import matplotlib.pyplot as plt
import prince
import plotly.io as pio
pio.renderers.default = 'browser'
import plotly.graph_objects as go
Importando Database
[perfil_aplicacao_civil.xlsx](https://prod-files-secure.s3.us-west-2.amazonaws.com/ed5c9723-2c6b-4e68-9eef-26f3e75b8625/9d507e4f-6dc9-402a-b45d-bac964bcad4d/perfil_aplicacao_civil.xlsx)
perfil_mca = pd.read_excel("perfil_aplicacao_civil.xlsx")
Limpando o banco para deixar somente as variáveis necessárias
perfil_mca = pd.read_excel("perfil_aplicacao_civil.xlsx")
Informações descritivas sobre as variáveis
print(dados_mca['perfil'].value_counts())
print(dados_mca['aplicacao'].value_counts())
print(dados_mca['estado.civil'].value_counts())
Analisando a tabela de configência
tabela_mca_1 = pd.crosstab(dados_mca["perfil"], dados_mca["aplicacao"])
tabela_mca_2 = pd.crosstab(dados_mca["perfil"], dados_mca["estado.civil"])
tabela_mca_3 = pd.crosstab(dados_mca["aplicacao"], dados_mca["estado.civil"])
print(tabela_mca_1)
print(tabela_mca_2)
print(tabela_mca_3)

Analisando a significância estatística das associações (teste qui²)
tab_1 = chi2_contingency(tabela_mca_1)
print("Associação Perfil x Aplicação")
print(f"estatística qui²: {round(tab_1[0], 2)}")
print(f"p-valor da estatística: {round(tab_1[1], 4)}")
print(f"graus de liberdade: {tab_1[2]}")
tab_2 = chi2_contingency(tabela_mca_2)
print("Associação Perfil x Estado Civil")
print(f"estatística qui²: {round(tab_2[0], 2)}")
print(f"p-valor da estatística: {round(tab_2[1], 4)}")
print(f"graus de liberdade: {tab_2[2]}")
tab_3 = chi2_contingency(tabela_mca_3)
print("Associação Aplicação x Estado Civil")
print(f"estatística qui²: {round(tab_3[0], 2)}")
print(f"p-valor da estatística: {round(tab_3[1], 4)}")
print(f"graus de liberdade: {tab_3[2]}")

Elaborando a MCA
mca = prince.MCA(n_components=2).fit(dados_mca
# Vamos parametrizar a MCA para duas dimensões (eixos X e Y no mapa perceptual)
# Note que o input é o próprio banco de dados com as variáveis categóricas)
Quantidade total de dimensões
# Quantidade de dimensões = qtde total de categorias - qtde de variáveis
# Quantidade total de categorias
mca.J_
# Quantidade de variáveis na análise
mca.K_
# Quantidade de dimensões
quant_dim = mca.J_ - mca.K_
# Resumo das informações
print(f"quantidade total de categorias: {mca.J_}")
print(f"quantidade de variáveis: {mca.K_}")
print(f"quantidade de dimensões: {quant_dim}")

Visualizando as matrizes: binária e Burt
# Nota: esta célula não é requerida para a função, tem fins didáticos!
binaria = pd.get_dummies(dados_mca, columns=dados_mca.columns, dtype=float)
burt = np.matmul(np.transpose(binaria), binaria)


Obtendo os eigenvalues
tabela_autovalores = mca.eigenvalues_summary
print(tabela_autovalores)

Inércia principal total
# Soma de todos os autovalores (todas as dimensões existentes)
print(mca.total_inertia_)

Obtendo as coordenadas principais das categorias das variáveis
coord_burt = mca.column_coordinates(dados_mca)
print(coord_burt)

Obtendo as coordenadas-padrão das categorias das variáveis
coord_padrao = mca.column_coordinates(dados_mca)/np.sqrt(mca.eigenvalues_)
print(coord_padrao)

Obtendo as coordenadas das observações do banco de dados
# Na função, as coordenadas das observações vêm das coordenadas-padrão
coord_obs = mca.row_coordinates(dados_mca)
print(coord_obs)

Plotando o mapa perceptual (coordenadas-padrão)
chart = coord_padrao.reset_index()
var_chart = pd.Series(chart['index'].str.split('_', expand=True).iloc[:,0])
# Nota: para a função acima ser executada adequadamente, não deixar underline no nome original da variável no dataset!
chart_df_mca = pd.DataFrame({'categoria': chart['index'],
'obs_x': chart[0],
'obs_y': chart[1],
'variavel': var_chart})
def label_point(x, y, val, ax):
a = pd.concat({'x': x, 'y': y, 'val': val}, axis=1)
for i, point in a.iterrows():
ax.text(point['x'] + 0.03, point['y'] - 0.02, point['val'], fontsize=5)
label_point(x = chart_df_mca['obs_x'],
y = chart_df_mca['obs_y'],
val = chart_df_mca['categoria'],
ax = plt.gca())
sns.scatterplot(data=chart_df_mca, x='obs_x', y='obs_y', hue='variavel', s=20)
sns.despine(top=True, right=True, left=False, bottom=False)
plt.axhline(y=0, color='lightgrey', ls='--', linewidth=0.8)
plt.axvline(x=0, color='lightgrey', ls='--', linewidth=0.8)
plt.tick_params(size=2, labelsize=6)
plt.legend(bbox_to_anchor=(0,0), fancybox=True, shadow=True, fontsize = '6')
plt.title("Mapa Perceptual - MCA", fontsize=12)
plt.xlabel(f"Dim. 1: {tabela_autovalores.iloc[0,1]} da inércia", fontsize=8)
plt.ylabel(f"Dim. 2: {tabela_autovalores.iloc[1,1]} da inércia", fontsize=8)
plt.show()

Exemplo 2 - Adaptação de estudantes no ensino remoto
Importando os pacotes
! pip install pandas
! pip install numpy
! pip install scipy
! pip install plotly
! pip install seaborn
! pip install matplotlib
! pip install statsmodels
! pip install prince
#%% Importando os pacotes necessários
import pandas as pd
import numpy as np
from scipy.stats import chi2_contingency
import statsmodels.api as sm
import seaborn as sns
import matplotlib.pyplot as plt
import prince
import plotly.express as px
import plotly.io as pio
pio.renderers.default = 'browser'
import plotly.graph_objects as go
from itertools import combinations
Importando o Banco de Dados
[estudantes_adapta.csv](https://prod-files-secure.s3.us-west-2.amazonaws.com/ed5c9723-2c6b-4e68-9eef-26f3e75b8625/f32fb7b2-8c11-4d07-8612-54358c384a7f/estudantes_adapta.csv)
dados_mca = pd.read_csv("estudantes_adapta.csv")
# Fonte: adaptado de https://www.kaggle.com/datasets/mdmahmudulhasansuzan/students-adaptability-level-in-online-education
# Suzan et al.(2021) Students' Adaptability Level Prediction in Online Education using Machine Learning Approaches - DOI: 10.1109/ICCCNT51525.2021.9579741

Analisando os dados do DB
print(dados_mca['Education'].value_counts())
print(dados_mca['Institution'].value_counts())
print(dados_mca['Financial'].value_counts())
print(dados_mca['Internet'].value_counts())
print(dados_mca['Adaptivity'].value_counts())

Analisando a tabela de Contigência
tabela_mca_1 = pd.crosstab(dados_mca["Adaptivity"], dados_mca["Education"])
tabela_mca_2 = pd.crosstab(dados_mca["Adaptivity"], dados_mca["Institution"])
tabela_mca_3 = pd.crosstab(dados_mca["Adaptivity"], dados_mca["Financial"])
tabela_mca_4 = pd.crosstab(dados_mca["Adaptivity"], dados_mca["Internet"])
print(tabela_mca_1)
print(tabela_mca_2)
print(tabela_mca_3)
print(tabela_mca_4)

Analisando a significância estatística das associações (teste qui²)
Adaptivity x Education
tab_1 = chi2_contingency(tabela_mca_1)
print("Adaptivity x Education")
print(f"estatística qui²: {round(tab_1[0], 2)}")
print(f"p-valor da estatística: {round(tab_1[1], 4)}")
print(f"graus de liberdade: {tab_1[2]}")

Adaptivity x Institution
tab_2 = chi2_contingency(tabela_mca_2)
print("Adaptivity x Institution")
print(f"estatística qui²: {round(tab_2[0], 2)}")
print(f"p-valor da estatística: {round(tab_2[1], 4)}")
print(f"graus de liberdade: {tab_2[2]}")

Adaptivity x Financial
tab_3 = chi2_contingency(tabela_mca_3)
print("Adaptivity x Financial")
print(f"estatística qui²: {round(tab_3[0], 2)}")
print(f"p-valor da estatística: {round(tab_3[1], 4)}")
print(f"graus de liberdade: {tab_3[2]}")

Adaptivity x Internet
tab_4 = chi2_contingency(tabela_mca_4)
print("Adaptivity x Internet")
print(f"estatística qui²: {round(tab_4[0], 2)}")
print(f"p-valor da estatística: {round(tab_4[1], 4)}")
print(f"graus de liberdade: {tab_4[2]}")

Elaborando a MCA
mca = prince.MCA(n_components=3).fit(dados_mca)
# Vamos parametrizar a MCA para três dimensões
# O objetivo é criar um mapa perceptual 3D
Quantidade total de dimensões
# Quantidade de dimensões = qtde total de categorias - qtde de variáveis
# Quantidade total de categorias
mca.J_
# Quantidade de variáveis na análise
mca.K_
# Quantidade de dimensões
quant_dim = mca.J_ - mca.K_
# Resumo das informações
print(f"quantidade total de categorias: {mca.J_}")
print(f"quantidade de variáveis: {mca.K_}")
print(f"quantidade de dimensões: {quant_dim}")

Obtendo os eigenvalues
tabela_autovalores = mca.eigenvalues_summary
print(tabela_autovalores)

Inércia principal total
# Soma de todos os autovalores (todas as dimensões existentes)
print(mca.total_inertia_)
média da inércia principal total por dimensão
# É interessante plotar apenas dimensões com autovalores maiores do que a média
print(mca.total_inertia_/quant_dim)
# Neste caso, as 3 dimensões extraídas têm autovalores > 0.199

Obtendo as coordenadas principais das categorias das variáveis
coord_burt = mca.column_coordinates(dados_mca)
print(coord_burt)

Obtendo as coordenadas-padrão das categorias das variáveis
coord_padrao = mca.column_coordinates(dados_mca)/np.sqrt(mca.eigenvalues_)
print(coord_padrao)

Obtendo as coordenadas das observações do banco de dados
# Na função, as coordenadas das observações vêm das coordenadas-padrão
coord_obs = mca.row_coordinates(dados_mca)
print(coord_obs)

Plotando o mapa perceptual (coordenadas-padrão)
# Primeiro passo: gerar um DataFrame detalhado
chart = coord_padrao.reset_index()
var_chart = pd.Series(chart['index'].str.split('_', expand=True).iloc[:,0])
nome_categ=[]
for col in dados_mca:
nome_categ.append(dados_mca[col].sort_values(ascending=True).unique())
categorias = pd.DataFrame(nome_categ).stack().reset_index()
chart_df_mca = pd.DataFrame({'categoria': chart['index'],
'obs_x': chart[0],
'obs_y': chart[1],
'obs_z': chart[2],
'variavel': var_chart,
'categoria_id': categorias[0]})
# Segundo passo: gerar o gráfico de pontos
fig = px.scatter_3d(chart_df_mca,
x='obs_x',
y='obs_y',
z='obs_z',
color='variavel',
text=chart_df_mca.categoria_id)
fig.show()
Exemplo 3 - Análise dos dados da Escala Likert
Instalando e chamando os módulos
! pip install pandas
! pip install numpy
! pip install scipy
! pip install plotly
! pip install seaborn
! pip install matplotlib
! pip install statsmodels
! pip install prince
#%% Importando os pacotes necessários
import pandas as pd
import numpy as np
from scipy.stats import chi2_contingency
import statsmodels.api as sm
import seaborn as sns
import matplotlib.pyplot as plt
import prince
import plotly.io as pio
pio.renderers.default = 'browser'
import plotly.graph_objects as go
Importando os dados
[gestao_municipal.xlsx](https://prod-files-secure.s3.us-west-2.amazonaws.com/ed5c9723-2c6b-4e68-9eef-26f3e75b8625/9d927065-2293-46fb-ad99-535531b98211/gestao_municipal.xlsx)
#Análise de Correspondência Simples (ANACOR)
# Importando o banco de dados
gestao = pd.read_excel("gestao_municipal.xlsx")
## Ao longo de 3 anos, foi aplicado questionário com a seguinte afirmação:
## Estou satisfeito com a gestão do atual prefeito!
## Respostas em escala likert de 5 pontos

Analisando as informações descritivas dos dados
print(gestao['avaliacao'].value_counts())
print(gestao['ano'].value_counts())

Criando a tabela de contingência
tabela = pd.crosstab(gestao["avaliacao"], gestao["ano"])
print(tabela)

Analisando a significância estatística da associação (teste qui²)
teste_qui2 = chi2_contingency(tabela)
print(f"estatística qui²: {round(teste_qui2[0], 2)}")
print(f"p-valor da estatística: {round(teste_qui2[1], 4)}")
print(f"graus de liberdade: {teste_qui2[2]}")

Mapa de calor dos resíduos padronizados ajustados
# Tabela de contingência
tab_cont = sm.stats.Table(tabela)
# Gráfico dos resíduos padronizados ajustados
fig = go.Figure()
maxz = np.max(tab_cont.standardized_resids)+0.1
minz = np.min(tab_cont.standardized_resids)-0.1
colorscale = ['lightgreen' if i>1.96 else '#FAF9F6' for i in np.arange(minz,maxz,0.01)]
fig.add_trace(
go.Heatmap(
x = tab_cont.standardized_resids.columns,
y = tab_cont.standardized_resids.index,
z = np.array(tab_cont.standardized_resids),
text=tab_cont.standardized_resids.values,
texttemplate='%{text:.2f}',
showscale=False,
colorscale=colorscale))
fig.update_layout(
title='Resíduos Padronizados Ajustados',
height = 600,
width = 600)
fig.show()
Elaborando a ANACOR
# Na função, o input é a tabela de contingência criada antes!
ca = prince.CA().fit(tabela)
Obtendo o eigenvalues
tabela_autovalores = ca.eigenvalues_summary
print(tabela_autovalores)
# São gerados 'm' autovalores: m = mín(I-1,J-1)

obtendo a inércia principal total
# É a soma dos eigenvalues (também é a divisão: estat. qui² / N)
# Quanto maior a inércia principal total, maior é a associação entre categorias
print(ca.total_inertia_)

Obtendo as coordenadas do mapa perceptual
# Coordenadas da variável em linha
print(ca.row_coordinates(tabela))
# Coordenadas da variável em coluna
print(ca.column_coordinates(tabela))

Plotando o mapa de percentual da Anacor
chart_df_row = pd.DataFrame({'var_row': tabela.index,
'x_row':ca.row_coordinates(tabela)[0].values,
'y_row': ca.row_coordinates(tabela)[1].values})
chart_df_col = pd.DataFrame({'var_col': tabela.columns,
'x_col':ca.column_coordinates(tabela)[0].values,
'y_col': ca.column_coordinates(tabela)[1].values})
def label_point(x, y, val, ax):
a = pd.concat({'x': x, 'y': y, 'val': val}, axis=1)
for i, point in a.iterrows():
ax.text(point['x'] + 0.03, point['y'] - 0.02, point['val'], fontsize=6)
label_point(x = chart_df_col['x_col'],
y = chart_df_col['y_col'],
val = chart_df_col['var_col'],
ax = plt.gca())
label_point(x = chart_df_row['x_row'],
y = chart_df_row['y_row'],
val = chart_df_row['var_row'],
ax = plt.gca())
sns.scatterplot(data=chart_df_row, x='x_row', y='y_row', s=20)
sns.scatterplot(data=chart_df_col, x='x_col', y='y_col', s=20)
sns.despine(top=True, right=True, left=False, bottom=False)
plt.axhline(y=0, color='lightgrey', ls='--', linewidth=0.8)
plt.axvline(x=0, color='lightgrey', ls='--', linewidth=0.8)
plt.tick_params(size=2, labelsize=6)
plt.title("Mapa Perceptual - Anacor", fontsize=12)
plt.xlabel(f"Dim. 1: {tabela_autovalores.iloc[0,1]} da inércia", fontsize=8)
plt.ylabel(f"Dim. 2: {tabela_autovalores.iloc[1,1]} da inércia", fontsize=8)
plt.show()

Obtendo as coordenadas das observações
# Identificando as variáveis em linha e em coluna
coord_obs = gestao.rename(columns={'avaliacao':'var_row',
'ano':'var_col'})
# Unindo as coordenadas das categorias ao DataFrame
coord_obs = pd.merge(coord_obs, chart_df_row, how='left', on='var_row')
coord_obs = pd.merge(coord_obs, chart_df_col, how='left', on='var_col')
# Calculando as coordenadas médias das observações (média de suas categorias)
coord_obs['x_obs'] = coord_obs['x_row','x_col'](/NaimeAndere/Study-Area/wiki/'x_row','x_col').mean(axis=1)
coord_obs['y_obs'] = coord_obs['y_row','y_col'](/NaimeAndere/Study-Area/wiki/'y_row','y_col').mean(axis=1)