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:

  1. 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.
  2. Cálculo das Proporções: Calculam-se as proporções relativas das frequências.
  3. Matriz de Perfis: Criação de perfis das linhas e colunas a partir das proporções.
  4. Centros de Massa: Determinação dos centros de massa das linhas e colunas.
  5. Análise dos Componentes Principais: Decomposição da matriz para obter os componentes principais que explicam a maior parte da variação nos dados.
  6. 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:

  1. Construção da Tabela de Dados: Uma tabela de dados é construída com várias variáveis categóricas.
  2. Conversão em Indicadoras: Cada categoria de cada variável é convertida em variáveis indicadoras (dummy variables).
  3. Matriz de Perfis: Criação de perfis das linhas e colunas a partir das variáveis indicadoras.
  4. Centros de Massa: Determinação dos centros de massa das linhas e colunas.
  5. Análise dos Componentes Principais: Decomposição da matriz para obter os componentes principais que explicam a maior parte da variação nos dados.
  6. 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")

Untitled

Informações descritivas sobre as variáveis

print(perfil['Perfil'].value_counts())
print(perfil['Tipo de Aplicação'].value_counts())

Untitled

Criando a tabela de contingência

Tabela = pd.crosstab(perfil["Perfil"], perfil["Tipo de Aplicação"])

Untitled

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]}")

Untitled

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)

Untitled

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)

Untitled

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]}")

Untitled

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}")

Untitled

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)

Untitled

Untitled

Obtendo os eigenvalues

tabela_autovalores = mca.eigenvalues_summary
print(tabela_autovalores)

Untitled

Inércia principal total

# Soma de todos os autovalores (todas as dimensões existentes)
print(mca.total_inertia_)

Untitled

Obtendo as coordenadas principais das categorias das variáveis

coord_burt = mca.column_coordinates(dados_mca)
print(coord_burt)

Untitled

Obtendo as coordenadas-padrão das categorias das variáveis

coord_padrao = mca.column_coordinates(dados_mca)/np.sqrt(mca.eigenvalues_)
print(coord_padrao)

Untitled

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)

Untitled

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()

Untitled

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

Untitled

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())

Untitled

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)

Untitled

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]}")

Untitled

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]}")

Untitled

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]}")

Untitled

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]}")

Untitled

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}")

Untitled

Obtendo os eigenvalues

tabela_autovalores = mca.eigenvalues_summary
print(tabela_autovalores)

Untitled

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

Untitled

Obtendo as coordenadas principais das categorias das variáveis

coord_burt = mca.column_coordinates(dados_mca)
print(coord_burt)

Untitled

Obtendo as coordenadas-padrão das categorias das variáveis

coord_padrao = mca.column_coordinates(dados_mca)/np.sqrt(mca.eigenvalues_)
print(coord_padrao)

Untitled

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)

Untitled

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

Untitled

Analisando as informações descritivas dos dados

print(gestao['avaliacao'].value_counts())
print(gestao['ano'].value_counts())

Untitled

Criando a tabela de contingência

tabela = pd.crosstab(gestao["avaliacao"], gestao["ano"])
print(tabela)

Untitled

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]}")

Untitled

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)

Untitled

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_)

Untitled

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))

Untitled

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()

Untitled

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)