Biblioteca FactorAnalyser



FactorAnalyzer é um módulo Python para realizar análise fatorial exploratórias (AFE) e confirmatória (AFC). Na análise exploratória se pode usar várias técnicas de estimativa. É possível executar AFE usando (1) solução residual mínima (MINRES), (2) uma solução de máxima verossimilhança ou (3) uma solução de fator principal. A análise confirmatória só pode ser executada usando uma solução de máxima verossimilhança.

As classes da biblioteca são compatíveis com scikit-learn. Partes do código são portadas da biblioteca psych do R, e a classe AFC foi baseada na biblioteca sem. A classe factor_analyzer.factor_analyzer.FactorAnalyzer se utiliza de sklearn.base.BaseEstimator e sklearn.base.TransformerMixin.

Na AFE as matrizes de carga fatorial são geralmente submetidas a rotações após o modelo de análise fatorial ser estimado, buscando-se produzir uma estrutura mais simples e de fácil interpretação na identificação das variáveis que estão carregando em um determinado fator.

Os dois tipos mais comuns de rotações são:

  • Rotação ortogonal varimax, que gira a matriz de cargas fatoriais de forma a maximizar a soma da variância das cargas quadradas, preservando a ortogonalidade da matriz de carga.
  • A rotação oblíqua promax, baseada na rotação varimax, mas buscando maior correlaçãp dos fatores.

Essa biblioteca inclui o módulo analisador de fatores com a classe FactorAnalyzer. Essa classe inclui os métodos fit() e transform() para realizar a análise e pontuar novos dados usando o modelo de fatores ajustados. Rotações opcionais podem ser realizadas sobre a matriz de cargas fatoriais com a classe Rotator.

Os seguintes métodos de rotação estão disponíveis tanto para FactorAnalyzer quanto para Rotator:

  • varimax (rotação ortogonal),
  • promax (oblíqua),
  • oblimin (oblíqua),
  • oblimax (ortogonal),
  • quartimin (oblíqua),
  • quartimax (ortogonal),
  • equamax (ortogonal),
  • geomin_obl (oblíqua),
  • geomin_ort (ortogonal).

A biblioteca também inclui o módulo confirmatory_factor_analyzer com a classe ConfirmatoryFactorAnalyzer. A classe contém os métodos fit() e transform() que realizam análises fatoriais confirmatórias e pontuam novos dados usando o modelo ajustado. A execução do CFA requer que os usuários especifiquem previamente o modelo com as relações de carga fatorial esperadas, o que pode ser feito usando a classe ModelSpecificationParser.

# A biblioteca pode ser instalada usando pip:
$ pip install factor_analyzer

# ou conda:
$ conda install -c ets factor_analyzer

Ele depende de Python 3.4 (ou superior), numpy, pandas, scipy, scikit-learn.

A classe factor_analyzer possui um método para ajustar um modelo de análise e fazer a análise fatorial usando solução residual mínima (MINRES), solução de máxima verossimilhança ou (3) solução de fator principal. Retorna a matriz de cargas fatoriais. Por default não realiza nenhuma rotação. Opcionalmente pode realizar uma rotação usando os métodos citados abaixo.

Análise Fatorial Exploratória

Módulo factor_analyzer.factor_analyzer

class
factor_analyzer.factor_analyzer.FactorAnalyzer(n_factors=3, rotation='promax', method='minres',
                                               use_smc=True, is_corr_matrix=False, bounds=(0.005, 1),
                                               impute='median', rotation_kwargs=None)
Parâmetros:
n_factors
(int, opcional) – Número de fatores a ajustar. Default: 3.
rotation
(str, opcional) – Default: None.
Define o tipo de rotação a realizar após o ajuste do modelo. Nenhuma rotação será realizada se rotation = None e nenhuma normalização de Kaiser será aplicada. Os seguintes métodos de rotação estão disponíveis:

  • varimax (rotação ortogonal),
  • promax (oblíqua),
  • oblimin (oblíqua),
  • oblimax (ortogonal),
  • quartimin (oblíqua),
  • quartimax (ortogonal),
  • equamax (ortogonal),

sendo rotation = ‘promax’ o default.

method
({‘minres’, ‘ml’, ‘principal’}, opcional) – Método de ajuste a ser usado: solução residual mínima (MINRES), uma solução de máxima verossimilhança ou de fator principal. Default: minres.
use_smc
(bool, opcional) – Uso de correlação multipla quadrada (SMC, square multiple correlation) como ponto de partida para a análise. Default: True.
bounds
(tuple, opcional) – Limites inferior e superior das variáveis para a otimização “L-BFGS-B”. Default: (0.005, 1).
impute
({‘drop’, ‘mean’, ‘median’}, opcional) – Se existem valores faltantes nos dados usar apagamento na lista inteira (‘drop’) ou substituir valores usando a mediana (‘median’) ou a média (‘mean’) da coluna.
use_corr_matrix
(bool, opcional) – Ajuste para Verdadeiro se os dados de entrada já são a matriz de correlação. Default: False.
rotation_kwargs
(opcional) – argumentos adicionais passados para o método de rotação.
Propriedades:
loadings
A matriz de cargas fatoriais. Default: None se o método fit() não foi chamado.
Tipo: numpy array
corr
A matriz original de correlação. Default: None se o método fit() não foi chamado.
Tipo: numpy array
rotation_matrix
A matriz de rotação, se uma rotação não foi executada.
Tipo: numpy array
structure
A estrutura da matriz de cargas fatoriais. (Só existe se rotação for promax).
Tipo: numpy array ou None
psi
A matriz de fatores de correlação. (Só existe se rotação for oblíqua).
Tipo: numpy array ou None
Métodos:
fit(X, y=None)
Faz a análise fatorial sobre os dados de X usando ‘minres’, ‘ml’, ou ‘principal solutions’. Default: SMC (correlação múltipla quadrada)
Parâmetros:
     X (variável tipo array) – Dados originais a serem analisados.
     y (não é utilizado).
get_communalities()
Calcula as comunalidades, dada uma matriz de cargas fatoriais.
Retorna: communalities (numpy array), as comunalidades.
get_eigenvalues()
Calcula os autovalores, dada uma matriz de correlações fatoriais.
Retorna: original_eigen_values (numpy array), os autovalores originais.
    common_factor_eigen_values(numpy array), os autovalores dos fatores comuns.
get_factor_variance()
Calcula informações de variância, inclusive a variância, variância proporcional e cumulativa para cada fator.
Retorna: variance (numpy array) – A variância dos fatores.
    proportional_variance (numpy array) – A variância proporcional dos fatores.
    cumulative_variances (numpy array) – A variância cumulativa dos fatores.
get_uniquenesses()
Calcula a unicidade, dada uma matriz de cargas fatoriais.
Retorna: uniquenesses (numpy array) – A unicidade da matriz de cargas fatoriais.
transform(X)
Retorna a pontuação de fatores para um novo conjunto de dados.
Parâmetros: X (variável de array, shape (n_amostras, n_características)) – Os dados a pontuar usando o modelo de fatores ajustado.
Retorna: X_new – As variáveis latentes de X. (um numpy array, shape (n_amostras, n_componentes))

Testes de Bartlett e KMO

factor_analyzer.factor_analyzer.calculate_bartlett_sphericity(x)

Testa a hipótese de que a matriz de correlação é igual à matriz identidade (o que significa que não há correlação entre as variáveis).

Parâmetro
X (variável de array) – Dados sobre os quais calcular a esfericidade.
Retorna:
statistic (float) – O valor de chi-quadrado, \chi^2.
p_value (float) – O valor de p-value associado ao teste.
factor_analyzer.factor_analyzer.calculate_kmo(x)

Calcula o critério de Kaiser-Meyer-Olkin para cada fator individual e para o conjunto fatores. Essa estatística representa o grau com que cada variável observada pode ser predita, sem erro, pelas demais variáveis. Na maior parte dos casos KMO < 0.6 é considerado inadequado.

Parâmetros:
x (variável de array) – Dados sobre os quais calcular coeficientes KMOs.
Retorna:
kmo_per_variable (array numpy) – O KMO para cada item.
kmo_total (float) – A pontuação KMO geral.

Análise Fatorial Confirmatória

Módulo factor_analyzer.confirmatory_factor_analyzer

class
factor_analyzer.confirmatory_factor_analyzer.ConfirmatoryFactorAnalyzer(specification=None,
                                n_obs=None, is_cov_matrix=False, bounds=None, max_iter=200,
                                tol=None, impute='median', disp=True)

A classe ConfirmatoryFactorAnalyzer ajusta um modelo de análise fatorial confirmatória usando o modelo de máxima verosimelhança (maximum likelihood).

Parâmetros:
specification
(ModelSpecification object ou None, opcional) – Um modelo de especificação ModelSpecification ou None. Se None for fornecido o ModelSpecification será gerado supondo que o número de fatores n_factors é o mesmo que o número de variáveis, n_variables, e que todas as variáveis carregam em todos os fatores. Note que isso pode significa que o modelo não foi identificado e a otimização poderá falhar. Default: None.
n_obs
(int ou None, opcional) – Número de observações no conjunto original de dados. Se não for passado e is_cov_matrix=True um erro será lançado. Default: None.
is_cov_matrix
(bool, opcional) – Informa se a matriz de entrada X é a matriz de covariância. Se False o conjunto completo de dados é considerado. Default: False.
bounds
(lista de tuplas ou None, opcional) – Uma lista de limites mínimos e máximos para cada elemento do array de entrada. Deve ser igual a x0 que é o array de entrada do modelo de especificação.

O comprimento é: ((n_factors * n_variables) + n_variables + n_factors + (((n_factors * n_factors) – n_factors) // 2)

Se bounds=None nenhum limite será tomado. Default: None.

max_iter
(int, opcional) – Número máximo de iterações na rotina de otimização. Default: 200.
tol
(float ou None, opcional) – Tolerância para a convergência. Default: None.
disp
(bool, opcional) – Se a mensagem da otimização do scipy fmin é enviado para o standard output. Default: True.
Exceção levantada
ValueError – Se is_cov_matrix = True e n_obs não é fornecido.
Propriedades:
model
Objeto modelo de especificação.
Tipo: ModelSpecification.
loadings_
A Matriz da Cargas fatoriais.
Tipo: numpy array
error_vars_
A matriz de variância de erros (Tipo: numpy array).
factor_varcovs_
A Matriz de covariância. (Tipo: numpy array).
log_likelihood_
O log de verossimilhança da rotina de otimização. (Tipo: float).
aic_
O critério de informação de Akaike. (Tipo: float).
bic_
O critério de informação Bayesiano. (Tipo: float).
Métodos:
fit(X, y=None)
realiza a análise fatorial confirmatória sobre os dados de X usando máxima verossimilhança.
Parâmetros:
X (variável tipo array) – Dados originais a serem analisados. Se X for a matriz de covariância é necessário marcar is_cov_matrix = True.
y (não é utilizado)
Exceção levantada:
ValueError – Se a especificação não é um objeto ModelSpecification nem None.
AssertionError – Se is_cov_matrix = True e a matriz fornecida não é quadrada.
AssertionError – If len(bounds) != len(x0)
get_model_implied_cov()
Retorna a matriz de covariância implícita no modelo, se o modelo foi estimado. (numpy array)
get_standard_errors()
Lê os erros padrão da matriz de covariância implícita e das médias implícitas.
Retorna:
loadings_se (numpy array) – Os erros padrões para os cargas fatoriais.
error_vars_se (numpy array) – Os erros padrões para as variâncias de erros.
transform(X)
Lê as pontuações para os fatores do novo conjunto de dados.
Parâmetros: X (tipo array, shape (n_amostras, n_características)) – Os dados a serem pontuados usando o modelo fatorial ajustado.
Retorna: pontuações – As variáveis latentes de X (um numpy array, shape (n_amostras, n_componentes))
class
factor_analyzer.confirmatory_factor_analyzer.ModelSpecification(loadings, n_factors, n_variables,
                                                                factor_names=None, variable_names=None)

Uma classe para encapsular a especificação do modelo para a análise confirmatória. Esta classe contém várias propriedades de especificação que são usadas no procedimento AFC.

Parâmetros:
loadings
(tipo array) – Especificação de cargas fatoriais.
error_vars (array-like) – Especificação de variância do erro
factor_covs (tipo array) – Especificação da covariância do fator.
factor_names (lista de str ou None) – uma lista de nomes de fatores, se disponível. Default: None.
variable_names (lista de str ou None) – Uma lista de nomes de variáveis, se disponível. Default: None.
Propriedades:
loadings
Especificação das cargas fatoriais. (Tipo: numpy array)
error_vars
Especificação da variância de erros. (Tipo: numpy array)
factor_covs
Especificação do fator de covariância. (Tipo: numpy array)
n_factors
Número de fatores. (Tipo: int).
n_variables
Número de variáveis. (Tipo: int).
n_lower_diag
Número de elementos no array factor_covs, igual à diagonal inferior da matriz de covariância fatorial. (Tipo: int).
loadings_free
Índices dos parâmetros de cargas fatoriais “livres”. (Tipo: numpy array)
error_vars_free
Índices dos parâmetros de variância de erros “livres”. (Tipo: numpy array)
factor_covs_free
Índices dos parâmetros de covariância de fator “livre”. (Tipo: numpy array)
factor_names
Lista dos nomes dos fatores, se disponível. (Tipo: lista de str ou None).
variable_names
Lista dos nomes das variáveis, se disponível. (Tipo: lista de str ou None).
error_vars
error_vars_free
factor_covs
factor_covs_free
factor_names
Métodos:
get_model_specification_as_dict()
Retorna model_specification – O modelo de especificações, chaves e valores, como um dicionario (dict).
copy()
Retorna uma “deep copy” do objeto.
loadings
loadings_free
n_factors
n_lower_diag
n_dtiables
dtiable_names

Analisador de especificação de modelo

class factor_analyzer.confirmatory_factor_analyzer.ModelSpecificationParser

Uma classe para gerar a especificação do modelo para Análise Fatorial Confirmatória. Inclui dois métodos estáticos para gerar o objeto ModelSpecification a partir de um dicionário ou de um array numpy.

static parse_model_specification_from_array(X, specification=None)

Gera a especificação do modelo a partir de um array. As colunas devem corresponder aos fatores e as linhas às variáveis. Se este método for usado para criar a ModelSpecification nenhum nome de fator ou nome de variável serão adicionadoa como propriedades desse objeto.

Parâmetros:
X (tipo array) – O conjunto de dados será usado para a AFC.
specification (tipo array or None) – Array com os detalhes das cargas.
Se specification = None a matriz será criada supondo-se que todas as variáveis carregam em todos os fatores. Default: None.
Retorna:
Objeto modelo de especificação, ModelSpecification.
Exceção levantada:
ValueError se especificação não está no formato esperado.
static parse_model_specification_from_dict(X, specification=None)

Gere a especificação do modelo a partir de um dicionário. As chaves no dicionário devem ser os nomes dos fatores e os valores devem ser os nomes das características (features). Se esse método for usado para criar uma ModelSpecification os nomes dos fatores e das variáveis serão adicionados como propriedades a esse objeto.

Parâmetros:
X (tipo array) – O conjunto de dados será usado para a AFC.
specification (tipo array or None) – Dicionário com os detalhes das cargas. Se None a matriz será criada supondo-se que todas as variáveis carregam em todos os fatores. Defaults = None.
Retorna: Objeto modelo de especificação, ModelSpecification.
Exceção levantada: ValueError se especificação não está no formato esperado.

Módulo factor_analyzer.rotator

Classe para executar diversas rotações nas matrizes de cargas fatoriais. Os métodos de rotação listados abaixo estão disponíveis tanto para FactorAnalyzer quanto para Rotator.

class
factor_analyzer.rotator.Rotator(method='varimax', normalize=True, power=4,
                                kappa=0, gamma=0, delta=0.01, max_iter=500, tol=1e-05)
Parâmetros:
method
(str, opcional). Métodos de rotação disponíveis: Default: ‘varimax’.

  • varimax (rotação ortogonal),
  • promax (oblíqua),
  • oblimin (oblíqua),
  • oblimax (ortogonal),
  • quartimin (oblíqua),
  • quartimax (ortogonal),
  • equamax (ortogonal),
  • geomin_obl (oblíqua),
  • geomin_ort (ortogonal).
normalize
(bool ou None, opcional) – Informa se uma normalização de Kaiser e de-normalização devem ser efetuadas antes e após a rotação. Usada para as rotações varimax e promax. Se None o default para promax é False, default para varimax é True. Default: None.
power
(int, opcional) – Potência das gargas de promax (menos 1). Geralmente na faixa entre 2 e 4. Default: 4.
kappa
(int, opcional) – Valor kappa para o objetivo equamax. Ignorado se método não for ‘equamax’. Default: 0.
gamma
(int, opcional) – Nível gamma para o objetivo ‘oblimin’. Ignorado se método não for ‘oblimin’. Default: 0.
delta
(float, opcional) – Nível delta level para o objetivo ‘geomin’. Ignorado se método não for ‘geomin_*’. Default: 0.01.
max_iter
(int, opcional) – Número máximo de iterações. Usado para método ‘varimax’ e rotações oblíquas. Default: 1000.
tol
(float, opcional) – Limite (threshold) de convergência. Usado para método ‘varimax’ e rotações oblíquas. Default: 1e-5.
Propriedades:
loadings_
A matriz de carregamentos. (Tipo: numpy array, shape (n_características, n_fatores)

rotation_

Matriz de rotação. (Tipo: numpy array, shape (n_fatores, n_fatores))

psi_

Matriz de correlações fatoriais. Existe apenas se a rotação é oblíqua. (Tipo: numpy array ou None)

Métodos:
fit(X, y=None)
Computa o fator de rotação model_specification – O modelo de especificações, chaves e valores, como um dicionario (dict).

Parâmetros
X (tipo array) – A matriz (n_características, n_fatores) de cargas fatoriais
y (não utilizado)
Retorna
self
fit_transform(X, y=None)
Computa o fator de rotação e retorna a nova matriz de cargas fatoriais.

Parâmetros
X (tipo array) – A matriz (n_características, n_fatores) de cargas fatoriais
y (não utilizado)
Retorna
loadings_, a matriz (n_características, n_fatores) de cargas fatoriais (numpy array)
Erro levantado
ValueError – se o método não está na lista de métodos aceitáveis.

Bibliografia

Jupyter Notebook


O que é o Jupyter Notebook?

Jupyter Notebook é uma ferramenta poderosa para o desenvolvimento projetos de ciência de dados de forma interativa que é executada de dentro de seu browser. Além da execução interativa de código ele pode ser usado para a preparação de apresentações dinâmicas onde texto pode ser bem formatado contendo imagens, gráficos interativos e fórmulas matemáticas. O conteúdo das linhas de código e seus outputs (as respostas produzidas pelo código) ficam bem delimitadas.

Ele faz parte do Projeto Jupyter de código aberto e free software. É possível baixar e instalar gratuitamente o Jupyter Notebooks separadamente ou como parte do kit de ferramentas de ciência de dados Anaconda. Com ele se pode usar vários ambientes de execução (kernels ou núcleos) com linguagens de programação como o Python, R, Julia, C++, Scheme, Haskell e Ruby.

O Jupyter Notebook está se tornando uma interface muito popular para a computação na nuvem e muitos dos provedores desse tipo de serviço o adotaram como interface front-end para seus usuários. Entre eles estão o SageMaker Notebooks da Amazon, o Colaboratory do Google e o Azure Notebook da Microsoft. O Colaboratory (também chamado de Colab) é um ambiente gratuito que armazena e roda notebooks no Google Drive.

Os arquivos no Notebook são armazenados no formato JSON com a extensão *.ipynb. Eles podem ser lidos pelo aplicativo instalado (que usa o browser para sua exibição), e exportado para várias formatos, entre eles: html, markdown, pdf, latex e slides Reveal.js. O arquivo consiste de várias células que são exibidas como uma página usual de html. Algumas células são de código e seus resultados, outras de texto, imagens ou outras mídias. Alternativamente eles podem ser lidos e exibidos (de forma não interativa) pelo nbviewer (na web).

Instalação

A forma mais simples de instalação do Jupyter Notebooks consiste em instalar o Anaconda, a distribuição Python mais usada para ciência de dados. Esta instalação inclui as princiais bibliotecas e ferramentas mais populares, como NumPy, Pandas e Matplotlib.

Para obter o Anaconda:

  • Baixe a versão mais recente do Anaconda aqui. Existem instaladores gráficos para Linux, Windows e MacOS.
  • Instale seguindo as instruções na página de download ou contidas no arquivo instalador executável.
  • ou … usuários que conhecem Python e que preferem gerenciar seus pacotes manualmente, pode apenas usar:
    pip3 install jupyter.

Executando e Criando um Notebook

No Windows na MacOS ou Linux um atalho para Jupyter Notebook é criado no menu do sistema. Caso nenhum atalho tenha sido criado você pode criar um ou iniciar usando o console. No Linux se digita jupyter-notebook no console. Uma janela com a seguinte aparência é aberta no browser padrão:

A primeira página exibe o painel de controle do Jupyter (dashboard). Ele dá acesso aos arquivos e subpastas que estão na pasta de inicialização do Jupyter. Esta pasta, no entanto, pode ser alterada. O painel de controle tem uma interface amigável por onde você pode controlar suas pastas e notebooks. Toda a descrição que usamos aqui se refere à aparência default dos notebooks. Essa aparência pode ser alterada modificando-se o arquivo css em /home/nome-usuario/.jupyter/custom/custom.css (no Linux).

O Jupyter Notebook fica aberto no navegador usando uma URL especial, do tipo “http://localhost:8888/tree”. Isso indica que o servidor dessa página esta em sua máquina local.

Você pode criar uma pasta nova para seus projetos clicando em New Folder. Depois pode renomear sua pasta selecionado e clicando em Rename. Clique na pasta para abrí-la e depois em New: Python 3 (notebook). Um notebook vazio e sem nome é criado. Clique nele e em File | Rename e dê um nome apropriado para o seu notebook. Vários notebooks podem ser abertos ao mesmo tempo.

Um notebook aberto apresenta a seguinte interface:

Os menus superiores dão acesso as funcionalidades de gravar arquivo, importar e exportar para diferentes formatos, etc. O item File | Save and Checkpoint (Ctrl-S) permite guardar o estado as sessão no momento de forma a poder ser recuperada mais tarde por meio de File | Revert to Checkpoint. Para fechar uma sessão não basta fechar a aba do navegador pois isso deixaria ativa a tarefa na memória do computador. Para isso você pode usar File | Close and Halt ou Kernel | Shutdown. Também se pode clicar em LOGOUT no canto superior direito.

Ainda na barra de menus você pode clicar em Help | User interface tour para ver alguns pontos relevantes no notebook. Help | Keyboard Shortcuts exibe os atalhos de teclado predefinidos, observando que eles podem ser modificados pelo usuário. O menu de ajuda também contém links diretos para as documentações do Python, IPython, NumPy, SciPy, Matplotlib, SymPy, pandas e markdown. O ícone de teclado abre uma ajuda com os atalhos mais usados.

Notebooks são iniciados com uma célula vazia. Cada célula possui dois modos de uso: modo de edição e modo de comando. Clicando dentro da célula ela fica com borda verde e entra no modo de edição onde se pode inserir texto e códigos. Use a caixa de seleção na caixa de ferramentas do notebook para selecionar entre ‘code’, ‘markdown’ ou ‘Raw NBConvert’. (A opção ‘heading’ está em desuso e é desnecessária). Se ‘code’ está selecionado você pode digitar um comando como, por ex.,

print('Olá galera!')
Olá galera!

Comandos dentro de uma célula de código são executados todos de uma vez. Para isso pressione:
shift-enter: o código é executado e uma nova célula é aberta no mode de edição, ou
ctrl-enter: o código é executado e a mesma célula fica selecionada no modo de comando.

Em ambos os casos o output, se existir, é mostrado abaixo da célula. O botão ▶ Run na barra de ferramentas tem o mesmo efeito que shift-enter.

Os modos de edição e de comando são alternados com o uso de ESC (passa de comando para edição) e enter (de edição para comando).

Quando no modo de comando (a célula fica com a borda azul) os seguintes atalhos ficam habilitados:

Comando Ação
ESC/enter Alterna entre modos de edição / comando
Barra de espaço Rolar tela para baixo
Shift-Barra de espaço Rolar tela para cima
A Inserir célula acima
B Inserir célula abaixo
D, D Apagar células selecionadas
Z Desfazer apagamento
Shift-L Exibir/ocultar numeração das linhas de código
Shift-Tab Exibir docstring de objeto
Y Alterar célula para código
M Alterar célula para markdown
R Alterar célula para raw
H Exibir Help | keyboard shortcuts
Teclas 🔼 ou 🔽 Rolar para cima e para baixo nas células
Shift 🔼 ou 🔽 Selecionar várias células de uma vez.
Shift M Mesclar várias células selecionadas em uma única.
Ctrl Shift – Dividir célula ativa na posição do cursor (no modo de edição).
Shift clique na margem esquerda da célula Selecionar várias células de uma vez.

Um lista completa desses atalhos pode ser vista no menu Help | keyboard shortcuts.

Células no formato de texto

Células podem ser marcadas como texto puro, sem qualquer formatação, no modo Raw NBConvert. Esse texto é exibido como está e não passará por renderização de nenhuma forma nem na exibição dentro do notebook nem na exportação para outros formatos, como o pdf.

Markdown

Markdown é uma linguagem de marcação limitada mas bastante simples de se aprender e usar. Ela tem sintaxe diferente de html mas guarda uma correspondência com suas tags. Você pode encontrar uma descrição mais completa de Markdown na página Marcação de Texto com Markdown.

Além da marcação markdown se pode usar um conjunto restrito de tags html nas caixas de texto. Por exemplo, o código seguinte:

 <div style = "border:1px solid black; padding:10px; color:white; background-color:red;" >
parei aqui ↷ 
</div>

produzirá a barra vermelha abaixo, útil para marcar um ponto específico dentro de um notebook.

parei aqui ↷

O Jupyter Notebook pode renderizar Latex (para isso usa a biblioteca javascript Mathjax) em suas células de Markdown.


A identidade de Euler é \(e^{i \pi} + 1 = 0\).
A definição da derivada de primeira ordem é:
$$
f'(x) = \lim\limits_{h \rightarrow 0} \frac{f(x+h) – f(x)}{h}
$$

Células de código

Células de código contém as instruções a serem executadas pelo kernel. À esquerda de uma célula de código aparece o sinal In[n] que significa Input [n], onde n é a ordem de execução das linhas. Uma célula em exibição é marcada pelo sinal In[*], o que é importante observar quando se tem uma execução mais demorada de código. Em geral o notebook continua responsivo mas novas instruções devem aguardar o término das primeiras para serem executados. O resultado da computação da célula, quando existir, aparece abaixo com o sinal Out[n].

O código em um célula ativa (com bordas azuis) é executado com ctrl-enter ou shift-enter (alternativamente com botão ▶ Run na barra de ferramentas). A barra de menu contém as opções Cell | Run All, Cell | Run All Above Cell | Run All Below.

É importante notar que as células são executadas no kernel e seu estado persiste ao longo da execução. O estado do kernel se refere ao notebook como um todo e não às células individuais. Se você importar bibliotecas ou declarar variáveis ​​em uma célula elas estarão disponíveis em toda a seção e não apenas nas células abaixo da declaração. A ordem em que inputs e outputs aparecem pode ser enganosa: se você declarar uma variável em uma célula, digamos g = 5 e voltar para uma célula anterior a variável g ainda terá o mesmo valor. O que importa é a ordem de execução, marcada por In[n]. Por isso é preciso ter cuidado ao fazer alterações nas células. Idealmente se deve manter a ordem sequencial e, ao fazer alterações importantes, executar todo o notebook novamente.

Existem várias opções relativas à execução no menu Kernel:

Kernel | Interrupt Interromper o kernel,
Kernel | Restart Reinicializar o kernel,
Kernel | Restart & clear outputs Reinicializar kernel e limpar outputs,
Kernel | Restart & Run All Reinicializar kernel e executar todas as células.

A opção de reinicializar o kernel limpando as saídas e executar novamente todas as células pode ser útil quando muitas células foram alteradas. No entanto, dependendo das operações a serem executadas, ela pode ser uma operação demorada.

É possível escolher e rodar e Jupyter Notebook com diferentes opções de kernel, com diferentes versões de Python e muitas outras linguagens, incluindo Java, C, R e Julia.

O Notebook é salvo ao se pressionar Ctrl S. Isso renova o arquivo de ponto de verificação que é criado junto com o Notebook. Esse arquivo, que também tem extensão .ipynb fica localizado em pasta oculta e pode ser usado na recuperação da sessão caso algum erro inesperado cause a perda do notebook atual. Por padrão o Jupyter salva automaticamente o bloco de notas a cada 120 segundos sem alterar o arquivo de bloco de notas principal.Para reverter para um ponto de verificação use o menu via File | Revert to Checkpoint.

Tendo escolhido um notebook com kernel python 3, podemos experimentar um resultado com a execução de código que fornece um output de texto e gráfico:

# importe as bibliotecas necessárias
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(1, 15, 0.1);
y = np.sin(x)/np.cos(x)
z = np.cos(x)/np.sin(x)
print("x em [1, 15] \ny=seno/cosseno; z=cosseno/seno")
plt.plot(x, y)
plt.plot(x, z)
x em [1, 15]
y=seno/cosseno; z=cosseno/seno

É importante observar que a última variável listada em uma célula é exibida no output sem necessidade de um comando print. Por ex., no código abaixo importamos uma tabela disponível na web no formato *.csv para a construção de um dataframe do pandas. O dataframe é exibido com uma formatação amigável no final da célula.

1  import pandas as pd
2  bfi ='https://vincentarelbundock.github.io/Rdatasets/csv/psych/bfi.csv'
3  df = pd.read_csv(bfi)
4  # head exibirá apenas as 5 primeiras linhas do dataframe
5  df.head()
Unnamed: 0 A1 A2 A3 A4 A5 C1 C2 C3 C4 N4 N5 O1 O2 O3 O4 O5 gender education age
0 61617 2.0 4.0 3.0 4.0 4.0 2.0 3.0 3.0 4.0 2.0 3.0 3.0 6 3.0 4.0 3.0 1 NaN 16
1 61618 2.0 4.0 5.0 2.0 5.0 5.0 4.0 4.0 3.0 5.0 5.0 4.0 2 4.0 3.0 3.0 2 NaN 18
2 61620 5.0 4.0 5.0 4.0 4.0 4.0 5.0 4.0 2.0 2.0 3.0 4.0 2 5.0 5.0 2.0 2 NaN 17
3 61621 4.0 4.0 6.0 5.0 5.0 4.0 4.0 3.0 5.0 4.0 1.0 3.0 3 4.0 3.0 5.0 2 NaN 17
4 61622 2.0 3.0 3.0 4.0 5.0 4.0 4.0 5.0 3.0 4.0 3.0 3.0 3 4.0 3.0 3.0 1 NaN 17

2800 rows × 29 columns

Ajuda

É sempre útil lembrar os mecanismos de se conseguir ajuda no python e no Jupyter. A função help do python é útil para se ver documentação sobre um tipo de variável ou uma bliblioteca importada. (Em ambos os casos a saída exibida está truncada.)

# ajuda sobre dictionaries
help(dict)
Help on class dict in module builtins:
class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object’s
| (key, value) pairs
| dict(iterable) -> new dictionary initialized as if via:
| d = {}
| for k, v in iterable:
| d[k] = v
import math
help(math)
Help on module math:
FUNCTIONS
acos(x, /)
Return the arc cosine (measured in radians) of x.
acosh(x, /)
Return the inverse hyperbolic cosine of x.
asin(x, /)
Return the arc sine (measured in radians) of x.

O comando help() usado sem argumento abre uma janela de busca interativa do tópico de ajuda.

Além disso escrever o nome de uma biblioteca, método ou variável precedido de ? provocará a exibição da docstring relativa ao item, o que é uma boa forma de conferir uso e sintaxe.

import pandas as pd
?pd
Type: module
String form: <module ‘pandas’ from ‘/home/guilherme/.anaconda3/lib/python3.7/site-packages/pandas/__init__.py’>
File: ~/.anaconda3/lib/python3.7/site-packages/pandas/__init__.py
Docstring:
pandas – a powerful data analysis and manipulation library for Python
=====================================================================
**pandas** is a Python package providing fast, flexible, and expressive data
structures [… texto truncado …]

Além disso é possível exibir a docstring de um objeto no Notebook apertando Shift-Tab após o nome do objeto dentro da célula.

Células e Linhas Mágicas em Jupyter

Uma sintaxe especial dos notebooks consiste em inserir comandos iniciados por %% para “mágica” na célula inteira e % para “mágica” na linha. Por exemplo %matplotlib inline faz com que gráficos do matplotlib sejam renderizados dentro do próprio notebook. Os sinais % e %%indicam respectivamente “mágica” na linha ou na célula. Digitar %lsmagic na célula e executá-la exibirá uma lista de todos os comandos mágicos de célula e de linha, informando ainda se automagic está ativado. Se automagic = ON os prefixos %% e % são desnecessários.

Alguns exemplos de “mágicas”:

Mágica Efeito
%run Roda um script externo como parte da célula.
Ex.: %run meu_codigo.py
executa meu_codigo.py como parte da célula.
%timeit Conta os loops, mede e exibe o tempo de execução da célula.
%prun Mostra o tempo de execução de uma função.
%%writefile Salva o conteúdo da célula para um arquivo.
Ex.: %%writefile meu_output.py
salva o código da célula no arquivo meu_output.py.
%%pycat Lê e exibe o conteúdo de um arquivo.
Ex.: %%pycat meu_output.py
lê o conteúdo gravada antes em meu_output.py.
%macro Define uma macro para execução posterior.
%store Salva a variável para uso em outro notebook.
%pwd Exibe a pasta default de trabalho.
%who Exibe varáveis ativas.
%matplotlib inline Exibe gráficos matplotlib inline.
%lsmagic Exibe lista de comandos “mágicos”.
%automagic Liga/desliga automagica (necessidade de %).
%%javascript Roda a célula como código JavaScript.
%%html Exibe código html renderizado.
%pdb Aciona o Python Debugger.
%<comando>? Mostra ajuda sobre a %<comando>
%%script python2
import sys
print 'Esse comando foi executado no Python %s' % sys.version
# output---> Esse comando foi executado no Python 2.7.18 (default, data / hora) 
%%script python3
import sys
print('Comando executado no Python: %s' % sys.version)
# output---> Esse comando foi executado no Python 3.8.5 (default, data / hora) 
%%bash
echo "O conteúdo de minha variável BASH: $BASH"
# output---> O conteúdo de minha variável BASH: /usr/bin/bash
# Definição de fatorial usando recursão	
def fatorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)
fatorial(40)      # resulta em 87178291200
# Claro que a mesma coisa seria obtida com a função
import math
print(math.factorial(14))    # 87178291200

Para medir o tempo de execução da célula ao rodar a função fatorial usamos %timeit

%timeit fatorial(14)

1.78 µs ± 16.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Executando comandos da SHELL

Usando o prefixo ! você pode enviar comandos diretamente para a shell de seu sistema operacional. Os comandos dependerão, claro, de seu sistema. No exemplo seguinte uso o bash do linux.

! ls *.ipynb     # vai listar todos os arquivos ipynb
! ls *.py        # lista meu_output.py gravado no exemplo anterior 

# mv é o comando bash para renomear arquivos
! mv meu_output.py novo_nome.py 
! ls *.py        # lista novo_nome.py

# Se você tem pip instalado pode gerenciar pacotes python de dentro do notebook:
!pip install --upgrade nome_do_pacote

Extensões do Jupyter Notebook


Extensões são recursos adicionais que estendem a funcionalidade dos Notebooks. Elas podem melhorar sua funcionalidade como uma IDE (um ambiente integrado de desenvolvimento), permitindo o acompanhamento de variáveis para fins de debugging, formatando o código automaticamente ou alterando sua aparência. Elas também permitem a inserção de widgets, que geralmente são objetos com representação gráfica no navegador, tais como caixas de texto, sliders e outras ferramentas interativas. Elas adicionam funcionalidades GUIs nos notebooks.

Uma extensão muito usada é a Nbextensions que pode ser instalada à partir do código seguinte, inserido no próprio notebook.

conda install -c conda-forge jupyter_contrib_nbextensions
conda install -c conda-forge jupyter_nbextensions_configurator 

A instalação de extensões pode variar de acordo com o seu ambiente de trabalho.

Jupyter Widgets

Widgets são objetos do python que possuem uma representação visual no navegador e permitem interação do usuário. Eles podem ser simples como uma caixa de texto ou um controle de arrastar, ou objetos sofisticados como os controles sobre uma tabela de dados ou sobre um mapa.

Slider é um widget útil para receber um valor do usuário por meio do mouse ou toque de tela. O objeto possui propriedades que podem ser alteradas e lidas, e métodos.
No exemplo abaixo um slider é criado, algumas de suas propriedades são ajustadas e depois é exibido.

import ipywidgets as ipw
# Inicializar um slider
slid = ipw.IntSlider()
slid.min = 0
slid.max = 50
slid.description = "Avalie:"
display(slid) # Exibe o slider ( figura a)

# O objeto pode ser inicializado com as propriedades desejadas
slid2 = ipw.IntSlider(
    value=0,
    min=0,
    max=10,
    step=2,
    description='Só pares:',
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    readout_format='d'
)
display(slid2) # Exibe o slider ( figura b)

Button é um widget que pode armazenar interação do usuário em resposta binária (sim/não, por ex.).

ipw.Button (
    description='Clica aí',
    disabled=False,
    tooltip='clica...',
    button_style='success', # pode ser 'success', 'info', 'warning', 'danger' ou ''
    icon='check'
)
# Exibe o botão (figura c)

Text apresenta uma caixa de texto a ser preenchida pelo usuário:

ipw.Text (
    placeholder='Digite seu nome',
    description='Nome:',
)
# Exibe a caixa de texto ( figura d)

Progress Bar mostra uma barra de progresso:

ipw.IntProgress (
    min=0,
    max=10,
    value=7,
    description='Realizado %',
    bar_style='success', # pode ser 'success', 'info', 'warning', 'danger' ou ''
    orientation='horizontal'
)
# Exibe a barra de progresso ( figura e)

Para serem úteis as widgets devem interagir com o código. Como ex. vamos criar uma barra de progresso atribuindo o objeto a uma variável.

pb = ipw.IntProgress (
    min=0,
    max=10,
    value=7,
    description='Realizado%',
    bar_style='success', # pode ser 'success', 'info', 'warning', 'danger' ou ''
    orientation='horizontal'
)

print('valor inicial = ', pb.value) # value é uma propriedade de pb. Neste caso seu valor é 7

pb.value = 10                       # que pode ser alterada no código
display(pb)	                        # exibe uma barra de progesso cheia

No exemplo seguinte fazemos uma interação entre os valores da barra de progresso com o clique de dois botões. O código usa o evento on_click dos botões para acionar as funções que aumentam e diminuem o valor da barra.

def aumentaBarra(s):
    pb.value +=1

def diminuiBarra(s):
    pb.value -=1

botaoMais = ipw.Button(description='Aumenta barra')
botaoMais.on_click(aumentaBarra)

botaoMenos = ipw.Button(description='Diminue barra')
botaoMenos.on_click(diminuiBarra)
# display(botaoMenos, botaoMais, pb)
# -- isso exibiria os controles um sobre o outro

# Para exibir os controles em uma linha única com título
# usamos HBox, Label

from ipywidgets import HBox, Label
HBox([Label('Em uma linha única:'), botaoMenos, botaoMais, pb])         # exibe figura (f)


Existem widgets mais sofisticados para formatação dos controles, inclusive com o uso de html e formatação css. Apenas para mostrar um exemplo segue o código abaixo, que usa HBox para construir uma linha e VBox para construir uma coluna de controles.

from ipywidgets import HBox, VBox, Label	
linha1 = HTML('<h2 style="color: red;">Use controles para modificar <i>progress box</i> </h2>')
linha2 = HBox([Label('Botões de controle:'), botaoMenos, botaoMais])
linha3 = pb
VBox([linha1, linha2, linha3]) # exibe figura (g)


Um clique no primeiro botão faz a barra de progressa avançar, no segundo faz a barra regredir.

Observe importamos os controles HBox,VBox e Label de ipywidget e, portanto eles podem ser usados diretamente sem menção à biblioteca de origem. Poderíamos usar a notação ipw.HBox para usar a caixa horizontal, sem precisar da importação explícita.

Outras informações sobre formatação dos widgets em
Layout and Styling of Jupyter widgets
.

Outros Widgets Úteis

HTMLMath serve para exibir equações matemáticas:

equacao = ipw.HTMLMath(
    value = r"Widgets podem ser usados para exibir equações inline \(x^2\) e destacadas $$\frac{x^2-1}{x-1}= x+1$$",
    placeholder='HTML',
    description='MathML:',
)
display(equacao)
MathML: Widgets podem ser usados para exibir equações inline \(x^2\) e destacadas $$\frac{x^2-1}{x-1}= x+1$$

ipyleaflet é uma biblioteca para a criação de mapas interativos que permitem marcação, arraste e ampliação. Em muitos casos, para executar um biblioteca recém instalada, pode ser necessário reinicializar o kernel.

# A biblioteca pode ser instalada com condas:
conda install -c conda-forge ipyleaflet

from ipyleaflet import Map
# inserindo as coordenadas da Praça da Liberdade em Belo Horizonte, MG
Map(center=[-19.932252,-43.9381638], zoom=15)

BeakerX é um pacote com widgets destinados a representar tabelas, gráficos, formulários de modo interativo. O widget de tabela reconhece e exibe dataframes do pandas. Ele facilita a pesquisa, e permite classificar, arrastar, filtrar, formatar ou selecionar células na tabela. Ele também permite a exportação para CSV ou área de transferência e a representação gráfica dos dados. O widget de tabela é mostrado abaixo, em imagem estática. Mais informações em Beakerx.

# Instalação do pacote
conda install -c conda-forge beakerx ipywidgets

import pandas as pd
from beakerx import *
pd.read_csv("UScity.csv")
# Instalando o pacote
conda install -c conda-forge k3d	

import k3d
plot = k3d.plot()
plot += k3d.points([0, 0, 0, 1, 1, 1])
plot.display()

A figura dentro do Notebook é dinâmica, podendo ser girada, ampliada, exportada, etc.

Modificando o estilo do Notebook

Jupyter Notebooks são enviados para o navegador como páginas html e são formatadas e estilizadas por meio de arquivos css (cascade style sheets) padrões. Para quem conhece html e css pode ser interessante editar diretamente esse arquivo. (Não se esqueça de fazer cópias de segurança dos arquivos que vai modificar).

Se sua instalação não contém a pasta “.jupyter” execute o comando jupyter notebook --generate-config no terminal. No Linux o arquivo de estilos está em /home/usuario/.jupyter/custom/custom.css, no Windows em pasta.do.python\Lib\site-packages\notebook\static\custom\custom.css, embora isso possa ser alterado ou ser diferente para outras instalações. Para ver a pasta onde está o arquivo de configurações você pode usar:

import jupyter_core
jupyter_core.paths.jupyter_config_dir()

Existem muitas folhas de estilo prontas para baixar, por exemplo no GitHub. Elas podem ser baixadas e copiadas para a pasta citada.

Para modificar apenas o estilo do Notebook aberto, sem alterar a aparência dos demais você pode usar:

# Importe biblioteca 
from IPython.core.display import HTML
HTML("<style> instruções de estilo </style>")
# Alternativamente se pode usar "mágica" em uma célula
%%html "<style> estilos - CSS </style>"

# Por exemplo, para atribuir margens laterais de 10% do tamanho da página use
display(HTML("<style>.container { margin: 0 10% 0 10% !important; }<style>"))

# Para exibir outputs em negrito
display(HTML("<style>.output_wrapper { font-weight: bold !important; }</style>"))

De dentro de um Notebook você pode carregar uma folha de estilo particular que passa a valer para aquele documento. Esse método é útil para formatar documentos de um tipo específico, por exemplo para uma apresentação ou páginas com estilos incomuns.

from IPython.core.display import HTML
def css_styling():
    styles = open("../styles/custom.css", "r").read()
    return HTML(styles)
css_styling()

Finalmente você pode instalar extensões tais como Jupyter themes.

Exportando e Compartilhando Notebooks


Notebooks podem ser exportados para diversos formatos tais como HTML e PDF e vários outros formatos. Isso pode ser encontrado no menu File | Download as. Se estiver trabalhando na nuvem a importação no formato nativo .ipynb serve para baixar para seu computador uma cópia do notebook. Ao subir uma cópia para o GitHub ou para o Colab você pode disponibilizar a sessão para outros colaboradores. Slides são úteis para aulas e apresentações.

NBViewer: NBViewer é um renderizador de notebooks, útil para quem quer ver uma sessão sem ter que necessariamente instalar o Jupyter. Esse é um serviço gratuito oferecido pelo Projeto Jupyter, disponível em nbviewer.jupyter.org. Ele recebe uma URL do notebook e o renderiza como página da web.

Bibliografia

  • Wintjen, Marc: Practical Data Analysis Using Jupyter Notebook: Learn how to speak the language of data by extracting useful and actionable insights using Python, Packt Publishing, Birmingham, UK, 2020.
  • Taieb, David: Thoughtful Data Science, , Packt Publishing, Birmingham, UK, 2018.
  • Dataquest: Advanced Jupyter Notebooks Tutorial, acessado em novembro de 2020.
  • Real Python: Jupyter Notebook Introduction, acessado em novembro de 2020.
  • Jupyter.org: Jupyter Main Site, acessado em novembro de 2020.
  • jupyter.org: Jupyter Widgets, acessado em novembro de 2020.

Análise Fatorial Usando Python

🔻Final do artigo

Para dar um exemplo de análise de fatores usaremos o módulo factor_analyser do Python. Os dados usados são originados do Synthetic Aperture Personality Assessment (SAPA) que contém 25 questões de auto-avaliação pessoais disponíveis na web na página de Vincent Arel-Bundock, no Github.

A documentação do Factor Analyser pode ser lida nessa página.

SAPA e BFI

SAPA, Synthetic Aperture Personality Assessment, é um método usado para avaliar diferenças de personalidade individuais, muito utilizado para pesquisas online. O sujeito testado recebe um subconjunto aleatório dos itens em estudo com o objetivo de reunir grande volume de dados suficientes para a montagem de grandes matrizes de covariância (de relacionamento entre os dados verificados). O teste online foi desenvolvido por William Revelle e é mantido pela Northwestern University, Ilinois, EUA.

O teste consiste dos seguintes ítens:
A1: Sou indiferente aos sentimentos das outras pessoas.
A2: Sempre pergunto sobre o bem-estar dos outros.
A3: Sei como confortar os outros.
A4: Adoro crianças.
A5: Faço as pessoas se sentirem à vontade.C1: Sou exigente no meu trabalho.
C2: Continuo minhas tarefas até que tudo esteja perfeito.
C3: Faço as coisas de acordo com um plano.
C4: Deixo tarefas semi-acabadas.
C5: Desperdiço meu tempo.E1: Não falo muito.
E2: Tenho dificuldades para abordar outras pessoas.
E3: Sei como cativar as pessoas.
E4: Faço amigos facilmente.
E5: Assumo o controle das situações.

N1: Fico com raiva facilmente.
N2: Irrito-me facilmente.
N3: Tenho alterações de humor frequentes.
N4: Muitas vezes me sinto triste.
N5: Entro em pânico facilmente.

O1: Sempre tenho muitas ideias.
O2: Evito leituras complexas.
O3: Procuro levar as conversas para um nível elevado.
O4: Passo algum tempo refletindo sobre as coisas.
O5: Nunca me detenho a avaliar um assunto profundamente.

Escala:
A escala usada para respostas usada foi:
1. Totalmente falso
2. Moderadamente falso
3. Um pouco falso
4. Um pouco correto
5. Moderadamente correto
6. Totalmente corretoIndicadores Demográficos:
estão codificados da seguinte forma:
Gênero:
1. Masculino,
2. Feminino.
Idade: a idade (em anos).
Educação:
1. Nível médio incompleto,
2. Nível médio completo,
3. Nível superior incompleto,
4. Nível superior completo,
5. Pós-graduação.Fatores esperados:
Os itens estão organizados por fatores esperados (a serem verificados pela análise):
Agreeableness, (Amabilidade),
Conscientiousness, (Conscienciosidade),
Extroversion, (Extroversão),
Neuroticism, (Neuroticismo) e
Opennness, (Abertura).

big 5
Diversos itens contribuem em grau maior ou menor para os fatores ou variáveis latentes.

O arquivo de respostas disponível foi baixado como o nome bfi.csv e salvo na pasta do projeto, subpasta ./dbs. Esse arquivo contém dados no formato *.csv (valores separados por vírgula) relativos a 2800 sujeitos com 3 campos adicionais de dados demográficos: sexo, educação e idade.

Jupyter Notebook e convenções usadas

Você pode ler sobre Jupyter Notebook nessa página.

Jupyter Notebook é uma aplicação web e opensource que permite sessões colaborativas e documentos compartilhados contendo código que pode ser executado dentro da página, equações bem formatadas, visualização gráfica e texto narrativo que podem ser postas sob forma de apresentações ou usadas para desenvolvimento. Seu uso inclui tratamento, transformação e visualização de dados, simulações numéricas, modelagem estatística, machine learning entre outras aplicações.

O projeto será rodado em uma sessão do Jupyter Notebook. Nessa página usamos as seguintes convenções: células de código do Jupyter Notebook aparecem dentro de caixas como a exibida abaixo. Nos notebooks (como no Python) linhas iniciadas pelo sinal “#” são comentários. Apenas nessas páginas outputs simples e compactos podem aparecer como um comentário após o comando como mostrado abaixo (diferente do que ocorre nos notebooks). Outpus mais complexos aparecem em caixas separadas.

# Exemplo de exibição das células do Jupyter Notebook.
print('output simples')    # Esse comando imprime 'output simples'

# Outpus mais complexos aparecem em caixas separadas:
print('Outputs do Jupyter Notebook, gráficos e dataframes exibidos aparecem como nesse quadro...')
Outputs do Jupyter Notebook, gráficos e dataframes exibidos aparecem como nesse quadro…

Módulo Factor Analyser

Veja mais sobre a documentação do Factor Analyser nessa página.

Factor Analyser é um módulo desenvolvido em Python por Jeremy Biggs e Nitin Madnani, publicado em 2017 para realizar análise fatorial exploratória e confirmatória (AFE, AFC). As classes do pacote são compatíveis com a biblioteca scikit-learn. Partes do código são portadas da biblioteca psych do R.

Tratamento dos dados do bsi por meio do factor_analyser

Instalamos o módulo factor_analyzer dentro do Jupyter Notebook. Em seguida importamos as bibliotecas necessárias: além do próprio factor_analyzer usamos o pandas e numpy para as manipelações de dados e matplotlib para as visualizações.

# Instalação do factor_analyzer:
conda install -c ets factor_analyzer

# Importando bibliotecas (libraries) necessárias
import pandas as pd
import numpy as np
from factor_analyzer import FactorAnalyzer
import matplotlib.pyplot as plt

# A leitura do arquivo de dados para dentro de um dataframe (do pandas)
df = pd.read_csv('./dbs/bfi.csv')

# Renomear a primeira coluna (que está sem nome) para 'id'
df.rename(columns = {'Unnamed: 0':'id'}, inplace = True) 
print('A tabela importada contém %d linhas, %d colunas' % df.shape)
print('contendo as seguintes colunas:\n', df.columns)

# Para visualizar a tabela importada:
df.head()
A tabela importada contém 2800 linhas, 29 colunas
contendo as seguintes colunas:
Index([‘id’, ‘A1’, ‘A2’, ‘A3’, ‘A4’, ‘A5’, ‘C1’, ‘C2’, ‘C3’, ‘C4’, ‘C5’, ‘E1’,
‘E2’, ‘E3’, ‘E4’, ‘E5’, ‘N1’, ‘N2’, ‘N3’, ‘N4’, ‘N5’, ‘O1’, ‘O2’, ‘O3’,
‘O4’, ‘O5’, ‘gender’, ‘education’, ‘age’],
dtype=’object’)
id A1 A2 A3 A4 A5 C1 C2 C3 C4 N4 N5 O1 O2 O3 O4 O5 gender education age
0 61617 2.0 4.0 3.0 4.0 4.0 2.0 3.0 3.0 4.0 2.0 3.0 3.0 6 3.0 4.0 3.0 1 NaN 16
1 61618 2.0 4.0 5.0 2.0 5.0 5.0 4.0 4.0 3.0 5.0 5.0 4.0 2 4.0 3.0 3.0 2 NaN 18
2 61620 5.0 4.0 5.0 4.0 4.0 4.0 5.0 4.0 2.0 2.0 3.0 4.0 2 5.0 5.0 2.0 2 NaN 17
3 61621 4.0 4.0 6.0 5.0 5.0 4.0 4.0 3.0 5.0 4.0 1.0 3.0 3 4.0 3.0 5.0 2 NaN 17
4 61622 2.0 3.0 3.0 4.0 5.0 4.0 4.0 5.0 3.0 4.0 3.0 3.0 3 4.0 3.0 3.0 1 NaN 17

2800 rows × 29 columns

Como em qualquer outro uso de dados, principalmente quando importados de fontes externas, fazemos uma verificação de estrutura e completeza ou a existência de valores ausentes (NaN). Os dados demográficos são armazendos em outro dataframe enquanto a avaliação das questões em si são deixadas no dataframe df depois de eliminados os campos relativos a dados demográficos.

# Tabela dfDemografico armazena id, sexo, educação e idade
dfDemografico = df[['id', 'gender', 'education', 'age']]

# Colunas desnecessárias são eliminadas de df
df.drop(['id', 'gender', 'education', 'age'],axis=1,inplace=True)

# Possíveis dados ausentes são eliminados
df.dropna(inplace=True)

# Para verificar as colunas de df
df.head(2)
A1 A2 A3 A4 A5 C1 C2 C3 C4 C5 N1 N2 N3 N4 N5 O1 O2 O3 O4 O5
0 2.0 4.0 3.0 4.0 4.0 2.0 3.0 3.0 4.0 4.0 3.0 4.0 2.0 2.0 3.0 3.0 6 3.0 4.0 3.0
1 2.0 4.0 5.0 2.0 5.0 5.0 4.0 4.0 3.0 4.0 3.0 3.0 3.0 5.0 5.0 4.0 2 4.0 3.0 3.0

2 rows × 25 columns

# Uma visão geral dos dados no dataframe df pode ser vista:
df.info()
<class ‘pandas.core.frame.DataFrame’>
Int64Index: 2436 entries, 0 to 2799
Data columns (total 25 columns):
# Column Non-Null Count Dtype
—————————————————————————————
0 A1 2436 non-null float64
1 A2 2436 non-null float64
2 A3 2436 non-null float64
3 A4 2436 non-null float64
4 A5 2436 non-null float64
Grupos C, E, N omitidos
20 O1 2436 non-null float64
21 O2 2436 non-null int64
22 O3 2436 non-null float64
23 O4 2436 non-null float64
24 O5 2436 non-null float64
dtypes: float64(24), int64(1)
memory usage: 494.8 KB

Observamos que apenas o campo O2 tem tipo de variável int64. Apenas para ter todos os campos do mesmo tipo fazemos a conversão para float64.

# Converter o campo O2 em float
df['O2'] = df['O2'].astype(np.float64)

type(df['O2'][0])    # Agora o campo é do tipo numpy.float64

Considerando que em operações que faremos podemos perder o nome das colunas, vamos armazenar esses nomes em uma varável (que nesse caso é uma série).

itens=df.columns
print(itens)
Index([‘A1’, ‘A2’, ‘A3’, ‘A4’, ‘A5’, ‘C1’, ‘C2’, ‘C3’, ‘C4’, ‘C5’, ‘E1’, ‘E2’,
‘E3’, ‘E4’, ‘E5’, ‘N1’, ‘N2’, ‘N3’, ‘N4’, ‘N5’, ‘O1’, ‘O2’, ‘O3’, ‘O4’,
‘O5′],
dtype=’object’)

Matriz de Correlação

Estamos prontos para encontrar a matriz de correlação entre as variáveis. Cada célula dessa matriz mostra a correlação entre duas variáveis, listadas como labels das linhas e colunas. Por isso ele tem os valores da diagonal iguais a 1 (que é a correlação da variável consigo mesma). A matriz de correlação fornece uma visão geral de interrelacionamento dos dados e é usada como input para análises mais advançadas.

A correlação .corr é um método de dataframes do pandas. Por default o método corr usa os coeficientes de Pearson mas também pode usar os coeficientes Tau de Kendall ou coefficientes de Spearman.

# A matriz de correlação entre todas as respostas na tabela
corrMatriz = df.corr()

# Para ver apenas as correlações entre variáveis do grupo A
corrMatriz[["A1", "A2","A3", "A4","A5"]].head(5)
A1 A2 A3 A4 A5
A1 1.000000 -0.350905 -0.273636 -0.156754 -0.192698
A2 -0.350905 1.000000 0.503041 0.350856 0.397400
A3 -0.273636 0.503041 1.000000 0.384918 0.515679
A4 -0.156754 0.350856 0.384918 1.000000 0.325644
A5 -0.192698 0.397400 0.515679 0.325644 1.000000

Em seguida fazemos o gráfico de calor (heatmap) da matriz de correlação. Usamos a biblioteca seaborn para isso. Um heatmap associa uma cor a cada valor na matriz de correção. Tons mais escuros de azul (nesse caso) são valores mais perto de 1, tons mais claros são valores mais perto de -1.

import seaborn as sns
plt.figure(figsize=(12,12))
sns.set(font_scale=1)
sns.heatmap(corrMatriz, linewidths=.1, linecolor='#ffffff',
            cmap='YlGnBu', xticklabels=1, yticklabels=1)


A mera análise do gráfico de calor permite que algumas características da pesquisa sejam visualmente reconhecidas. Duas variáveis diferentes com índice de correlação muito alto podem ser, na verdade, a mesma variável escrita de forma diversa. Nesse caso o pesquisador pode preferir retirar uma delas. Uma ou mais variáveis com nível de correlação muito baixo com todas as demais podem indicar a medida de elementos isolados e fora de contexto com o modelo explorado. Nesse caso vemos agrupamentos claros entre as variáveis A2, A3, A4, A5 e todas as do grupo N, só para citar alguns exemplos.

Análise Fatorial

Análise Fatorial Exploratória, AFE

Podemos agora dar início ao uso específico da Análise Fatorial, começando pela Análise Fatorial Exploratória, AFE, usando o módulo factor_analyzer. O primeiro passo para isso é a avaliação da fatorabilidade dos dados. Isso significa que os dados coletados podem ser agrupados em fatores, que são as nossas variáveis ocultas com o poder de sintetizar e melhor descrever o objeto estudado. Para isso o módulo factor_analyzer oferece dois testes: o Teste de Bartlett e o Teste de Kaiser-Meyer-Olkin.

Teste da esfericidade de Bartlett

O Teste da esfericidade de Bartlett verifica se as variáveis estão correlacionadas entre si, comparando a matriz de correlação com a matriz identidade (que representaria variáveis completamente não correlacionadas).

# Importa o módulo que realiza o teste de Bartlett
from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity
chi_square_value, p_value = calculate_bartlett_sphericity(df)
print('Teste da Esfericidade de Bartlett: chi² = %d,  p_value = %d' % (chi_square_value, p_value))
Teste da Esfericidade de Bartlett: chi2 = 18170.966350869272 p_value = 0.

No nosso caso o teste de Bartlett resulta em p-value = 0, o que indica que os dados podem ser fatorados e a matriz de correlação observada não é a identidade.

Teste de Kaiser-Meyer-Olkin

O Teste de Kaiser-Meyer-Olkin (KMO) fornece uma técnica de avaliação se os dados colhidos são apropriados para esta análise fatorial. Ele realiza um teste para cada variável observada e para o conjunto completo de variáveis. O resultado representa o grau em que cada variável observada pode ser predita, sem erros, pelas demais variáveis no conjunto de dados. KMO é uma estimativa da proporção de variância entre todas as variáveis. Os valores de KMO podem estar entre 0 e 1 e valores abaixo de 0.6 são consideredos inadequados.

# Importa calculate_kmo
from factor_analyzer.factor_analyzer import calculate_kmo
kmo_all,kmo_model = calculate_kmo(df)

print('Valores de kmo_all =\n', kmo_all, '\n')
print('KMO =', kmo_model)
Valores de kmo_all =
[0.75391928 0.8363196 0.87010963 0.87795367 0.90348747 0.84325413
0.79568263 0.85186857 0.82647206 0.86401687 0.83801873 0.88380544
0.89697008 0.87731273 0.89332158 0.77933902 0.78025018 0.86229919
0.88518467 0.86014155 0.85858672 0.78019798 0.84434957 0.77003158
0.76144469]KMO = 0.848539722194922

Todos os valores de kmo_all são superiores a 0,7 e o KMO geral é KMO = 0.8485 o que são considerados valores muito favoráveis para a análise dos fatores.

Prosseguimos criando uma instância do objeto factor_analysis, tentativamente com 5 fatores

# Criamos objeto factor_analysis, sem rotação e usando 5 fatores (tentativamente)
fa = FactorAnalyzer(5, rotation=None)

# Aplicamos o método fit (ajuste) desse objeto no dataframe
fa.fit(df)

# Depois desse ajuste podemos coletar os autovetores e autovalores
ev, v = fa.get_eigenvalues()
print('São ' + str(len(ev)) + ' autovalores:\n', ev)
São 25 eigenvalues:
[5.13431118 2.75188667 2.14270195 1.85232761 1.54816285 1.07358247
0.83953893 0.79920618 0.71898919 0.68808879 0.67637336 0.65179984
0.62325295 0.59656284 0.56309083 0.54330533 0.51451752 0.49450315
0.48263952 0.448921 0.42336611 0.40067145 0.38780448 0.38185679
0.26253902]

Usando os autovalores calculados traçamos um Screeplot que é um gráfico que lista os autovalores em ordem decrescente, usado para determinar o número de fatores a serem retidos em uma análise fatorial exploratória. O teste, introduzido por R.B. Cattell em 1966, sugere manter tantos fatores quantos forem as autovalores anteriores a uma “dobra mais acentuada” ou “cotovelo” no gráfico. Também é sugerido manter o mesmo número de fatores quantos autovalores existirem maiores que 1.

from bokeh.plotting import figure, output_notebook, show
output_notebook()

eixoX = range(1, len(ev)+1)   # de 1 0 26
eixoY = ev
p = figure(title="Scree Plot", x_axis_label='n-ésimo autovalor',y_axis_label='autovalor',
           x_range=[0,25], y_range=(0, 6), plot_width=600, plot_height=400,
           background_fill_color="#c9b2dd")

p.line(eixoX, eixoY, line_width=1, color = 'black')
p.circle(eixoX, eixoY, size=8, fill_color='red', color="black")

show(p)

Algumas críticas são dirigidas ao teste feito dessa forma pois ele insere uma decisão pouco objetiva. Mais de um cotovelo podem aparecer no gráfico. De qualquer forma, como veremos no presente caso, o bom senso e a análise posterior dos agrupamentos de fatores podem sugerir uma alteração nesse número.

Cargas Fatoriais (factor loadings)

A carga fatorial é o coeficiente de correlação entre a variável e o fator. Ela mostra a variância explicada pela variável naquele fator em particular.

Prosseguimos criando um objeto FactorAnalyzer com 6 fatores (tentativamente) e usando o método de rotação varimax.

# 6 fatores
fa = FactorAnalyzer( 6, rotation="varimax")

# o objeto tem o método fit para análise do dataframe
fa.fit(df)

# Desse extraimos as cargas fatoriais (factor loadings)
# Observe que fa.loadings_ é um numpy.array com shape (25,6). Usamos o método
# do pandas pd.DataFrame.from_records para convertê-lo em um dataframe
factorLoadings = pd.DataFrame.from_records(fa.loadings_)

# Para ver a dataframe gerado:
factorLoadings.head(4)
0 1 2 3 4 5
0 0.095220 0.040783 0.048734 -0.530987 -0.113057 0.161216
1 0.033131 0.235538 0.133714 0.661141 0.063734 -0.006244
2 -0.009621 0.343008 0.121353 0.605933 0.033990 0.160106
3 -0.081518 0.219717 0.235140 0.404594 -0.125338 0.086356

Vemos que os nomes dos itens, de A1 até O5, foram perdidos no cálculo. Vamos renomear tanto esses itens quanto os nomes das colunas (que são os fatores) para ter uma visualização mais clara do que obtivemos até aqui:

# Substitue as linhas pelo nomes dos itens
factorLoadings.index=itens

# Renomeia as colunas
factorLoadings.rename(columns = {0:'Fator 1',
                                 1:'Fator 2',
                                 2:'Fator 3',
                                 3:'Fator 4',
                                 4:'Fator 5',
                                 5:'Fator 6'}, inplace = True)

# Exibe o resultado
factorLoadings
Fator 1 Fator 2 Fator 3 Fator 4 Fator 5 Fator 6
A1 0.095220 0.040783 0.048734 -0.530987 -0.113057 0.161216
A2 0.033131 0.235538 0.133714 0.661141 0.063734 -0.006244
A3 -0.009621 0.343008 0.121353 0.605933 0.033990 0.160106
A4 -0.081518 0.219717 0.235140 0.404594 -0.125338 0.086356
A5 -0.149616 0.414458 0.106382 0.469698 0.030977 0.236519
C1 -0.004358 0.077248 0.554582 0.007511 0.190124 0.095035
C2 0.068330 0.038370 0.674545 0.057055 0.087593 0.152775
C3 -0.039994 0.031867 0.551164 0.101282 -0.011338 0.008996
C4 0.216283 -0.066241 -0.638475 -0.102617 -0.143846 0.318359
C5 0.284187 -0.180812 -0.544838 -0.059955 0.025837 0.132423
E1 0.022280 -0.590451 0.053915 -0.130851 -0.071205 0.156583
E2 0.233624 -0.684578 -0.088497 -0.116716 -0.045561 0.115065
E3 -0.000895 0.556774 0.103390 0.179396 0.241180 0.267291
E4 -0.136788 0.658395 0.113798 0.241143 -0.107808 0.158513
E5 0.034490 0.507535 0.309813 0.078804 0.200821 0.008747
N1 0.805806 0.068011 -0.051264 -0.174849 -0.074977 -0.096266
N2 0.789832 0.022958 -0.037477 -0.141134 0.006726 -0.139823
N3 0.725081 -0.065687 -0.059039 -0.019184 -0.010664 0.062495
N4 0.578319 -0.345072 -0.162174 0.000403 0.062916 0.147551
N5 0.523097 -0.161675 -0.025305 0.090125 -0.161892 0.120049
O1 -0.020004 0.225339 0.133201 0.005178 0.479477 0.218690
O2 0.156230 -0.001982 -0.086047 0.043989 -0.496640 0.134693
O3 0.011851 0.325954 0.093880 0.076642 0.566128 0.210777
O4 0.207281 -0.177746 -0.005671 0.133656 0.349227 0.178068
O5 0.063234 -0.014221 -0.047059 -0.057561 -0.576743 0.135936

Vamos montar mais um heatmap com essa tabela.

# A bibioteca seaborn já foi importada como sns
plt.figure(figsize=(8,6))
sns.set(font_scale=.9)
sns.heatmap(factorLoadings,  linewidths=1, linecolor='#ffffff', cmap="YlGnBu", xticklabels=1, yticklabels=1)

Lembrando que as cores mais escuras indicam correlação direta e as mais claras correlação inversa, percebemos que existem cargas mais fortes entre os itens N1, N2, N3, N4 e N5 com o fator 1, E1 até E5 no fator 2, etc. Nenhum dos itens, no entanto, tem carga relevante no sexto fator. Isso indica que podemos refazer o cálculo de cargas fatoriais com apenas 5 fatores.

# Refazendo o cáculo com 5 fatores apenas
# Apaga a variável fa
del fa

fa = FactorAnalyzer( 5, rotation="varimax")
fa.fit(df)
factorLoadings = pd.DataFrame.from_records(fa.loadings_)

# Renomeia itens
factorLoadings.index=itens

# Renomeia as colunas (fatores)
factorLoadings.rename(columns = {0:'Fator 1',
                                 1:'Fator 2',
                                 2:'Fator 3',
                                 3:'Fator 4',
                                 4:'Fator 5'}, inplace = True)

# Exibe o resultado
factorLoadings
Fator 1 Fator 2 Fator 3 Fator 4 Fator 5
A1 0.111126 0.040465 0.022798 -0.428166 -0.077931
A2 0.029588 0.213716 0.139037 0.626946 0.062139
A3 0.009357 0.317848 0.109331 0.650743 0.056196
A4 -0.066476 0.204566 0.230584 0.435624 -0.112700
A5 -0.122113 0.393034 0.087869 0.537087 0.066708
C1 0.010416 0.070184 0.545824 0.038878 0.209584
C2 0.089574 0.033270 0.648731 0.102782 0.115434
C3 -0.030855 0.023907 0.557036 0.111578 -0.005183
C4 0.240410 -0.064984 -0.633806 -0.037498 -0.107535
C5 0.290318 -0.176395 -0.562467 -0.047525 0.036822
E1 0.042819 -0.574835 0.033144 -0.104813 -0.058795
E2 0.244743 -0.678731 -0.102483 -0.112517 -0.042010
E3 0.024180 0.536816 0.083010 0.257906 0.280877
E4 -0.115614 0.646833 0.102023 0.306101 -0.073422
E5 0.036145 0.504069 0.312899 0.090354 0.213739
N1 0.786807 0.078923 -0.045997 -0.216363 -0.084704
N2 0.754109 0.027301 -0.030568 -0.193744 -0.010304
N3 0.731721 -0.061430 -0.067084 -0.027712 -0.004217
N4 0.590602 -0.345388 -0.178902 0.005886 0.075225
N5 0.537858 -0.161291 -0.037309 0.100931 -0.149769
O1 -0.002224 0.213005 0.115080 0.061550 0.504907
O2 0.175788 0.004560 -0.099729 0.081809 -0.468925
O3 0.026736 0.310956 0.076873 0.126889 0.596007
O4 0.220582 -0.191196 -0.021906 0.155475 0.369012
O5 0.085401 -0.005347 -0.062730 -0.010384 -0.533778

Construimos o heatmap com essa tabela de 5 fatores.

plt.figure(figsize=(8,6))
sns.set(font_scale=.9)
sns.heatmap(factorLoadings,  linewidths=1, linecolor='#ffffff', cmap="YlGnBu", xticklabels=1, yticklabels=1)
Os retângulos de borda
preta indicando grupos
de correlação foram
acrescentados manualmente.

Pelo heatmap percebemos que o grupo de itens N está associado ao fator 1 (Neuroticismo), E ao fator 2 (Extroversão), C ao fator 3 (Conscienciosidade), A ao fator 4 (Amabilidade) e O ao fator 5 (Abertura), previamente identificados. É claro que essa identificação do fator foi realizada pelos pesquisadores no caso dessa pesquisa em particular. Para uma pesquisa nova seria necessário um estudo para o entendimento da natureza de cada fator.

Observe ainda que correlação negativa é correlação. É o que ocorre, por exemplo entre os itens A1 (Sou indiferente aos sentimentos das outras pessoas) e A2 (Sempre pergunto sobre o bem-estar dos outros). A correlação entre eles pode ser obtida da matriz de correlação, corrMatriz['A1']['A2'] = -0.35091.

Observamos que existem as seguintes correspondências entre os grupos de questões e os fatores propostos:

Fator Grupo Descrição
1 N Neuroticismo
2 E Extroversão
3 C Conscienciosidade
4 A Amabilidade
5 O Abertura

Vamos, portanto, renomear as colunas de nossa matriz de cargas fatoriais para refletir esse entendimento:

# Renomeia as colunas (fatores)
factorLoadings.rename(columns = {'Fator 1':'Neuroticismo',
                                 'Fator 2':'Extroversão',
                                 'Fator 3':'Conscienciosidade',
                                 'Fator 4':'Amabilidade',
                                 'Fator 5':'Abertura'}, inplace = True)

# Exibe o resultado (só duas linhas)
factorLoadings.head(2)	
Neuroticismo Extroversão Conscienciosidade Amabilidade Abertura
A1 0.111126 0.040465 0.022798 -0.428166 -0.077931
A2 0.029588 0.213716 0.139037 0.626946 0.062139

Comunalidades

Comunalidades são a soma das cargas fatoriais ao quadrado de cada variável medida. Denotando por \(l_{ij}\) os elementos da matriz da cargas fatoriais a comunalidade da i-ésima variável é \(h_i^2\) dado por
$$
h_i^2 =\Sigma_{j=1}^n l_{ij}^2
$$
Por exemplo, a comunalidade relativa à questão A1 é a soma dos elementos (ao quadrado) da primeira linha da matriz de cargas fatoriais acima:

(0.111126)**2 + (0.040465)**2 + (0.022798)**2 + (-0.428166)**2 +(-0.077931)**2
0.203905517222

As comunalidades relativas a todas as variáveis podem ser obtidas com get_communalities() que retorna um numpy.ndarray com dimensões (25,):

fa.get_communalities()
array([0.20390517, 0.46280338, 0.53969218, 0.30190473, 0.47002029,
0.34839471, 0.45387181, 0.32428892, 0.47669926, 0.43538283,
0.34780933, 0.545502 , 0.44105495, 0.54125654, 0.40714621,
0.68139838, 0.60800298, 0.54447487, 0.50580328, 0.34931564,
0.31733902, 0.26745151, 0.47464268, 0.2460347 , 0.29628368])

A soma de todos os valores de comunalidade é o valor de comunalidade total:

fa.get_communalities().sum()
10.590479059488883

Para exibir uma tabela com os nomes da variáveis e suas respectivas comunalidades vamos construir um dataframe contendo esses dados. Lembrando que já temos a variável itens = ['A1', 'A2', ..., 'O4','O5']:

dfComunalidades = pd.DataFrame(comunalidades)
dfComunalidades.index = itens
Variável Comunalidade
A1 0.203905
A2 0.462803
A3 0.539692
A4 0.301905
A5 0.470020
C1 0.348395
C2 0.453872
C3 0.324289
C4 0.476699
C5 0.435383
Variável Comunalidade
E1 0.347809
E2 0.545502
E3 0.441055
E4 0.541257
E5 0.407146
N1 0.681398
N2 0.608003
N3 0.544475
N4 0.505803
N5 0.349316
Variável Comunalidade
O1 0.317339
O2 0.267452
O3 0.474643
O4 0.246035
O5 0.296284
Total 10.5905
Como temos 25 fatores:
Total/25 0.4236

Podemos pensar na comunalidade de uma variável como a proporção de variação nessa variável explicada pelos fatores propostos no modelo. Por exemplo, a variável N1 tem a maior comunalidade (0.681398) nesse modelo, indicando que aproximadamente 69% da variação nas respostas para “N1: Fico com raiva facilmente” é explicada pelo modelo de 5 fatores proposto enquanto esse valor é de apenas 20% para “A1: Sou indiferente aos sentimentos das outras pessoas”.

Comunalidades servem para avaliar o desempenho do modelo. Valores mais próximos de um indicam que o modelo explica a maior parte da variação para essas variáveis. Nesse caso o modelo está melhor ajustado para as variáveis do grupo N (neuroticismo)​ e menos eficiente para as variáveis do grupo O (abertura)​.

A Comunalidade total é de 10.5905 que, dividido entre as 25 variáveis indica uma média de 10.5905/25 = 0.4236 geral para o modelo, ou seja, uma eficiência média de 42% do modelo em explicar a variação de cada variável do teste.

🔺Início do artigo

Bibliografia