Análise Fatorial com o pacote psych

Author

Jessica Kubrusly

Published

June 13, 2025

#Instalar (caso ainda não tenha)
#install.packages("psych")
#install.packages("GPArotation")

library(tidyverse)
library(psych)
library(GPArotation)

Introdução

A análise fatorial é uma técnica estatística usada para identificar estruturas latentes em um conjunto de variáveis. Utilizaremos o pacote {psych} do R, que fornece funções úteis para esse tipo de análise.

Importação dos Dados

Esse relatório será baseado na Tabela 8.4 do livro texto, que contém informações sobre 5 ações da bolsa de valores.

dados = read_csv("tabela_8_4.csv")
glimpse(dados)
Rows: 103
Columns: 5
$ JPMORGAN        <dbl> 0.0130338, 0.0084862, -0.0179153, 0.0215589, 0.0108225…
$ CITIBANK        <dbl> -0.0078431, 0.0166886, -0.0086393, -0.0034858, 0.00371…
$ WELLSFARGO      <dbl> -0.0031889, -0.0062100, 0.0100360, 0.0174353, -0.01013…
$ ROYALDUTCHSHELL <dbl> -0.0447693, 0.0119560, 0.0000000, -0.0285917, 0.029190…
$ EXXONMOBIL      <dbl> 0.0052151, 0.0134890, -0.0061428, -0.0069534, 0.040975…

Verificação da Adequação da Análise Fatorial

Antes de aplicar a análise fatorial, é importante verificar:

  • KMO (Kaiser-Meyer-Olkin)
  • Teste de Esfericidade de Bartlett

O teste KMO avalia a adequação da amostragem para análise fatorial, verificando se as variáveis têm correlações parciais baixas (ou seja, se há correlações comuns suficientes para justificar a formação de fatores).

Interpretação dos valores para Overall MSA: 0.90 a 1.00, Excelente; 0.80 a 0.89, Muito bom; 0.70 a 0.79, Bom; 0.60 a 0.69, Razoável; 0.50 a 0.59, Ruim; Abaixo de 0.50, Inadequado (não fazer análise fatorial).

Os MSAs individuais ajudam a identificar variáveis problemáticas. Se alguma variável tiver \(MSA < 0.50\), ela pode estar atrapalhando a estrutura fatorial e deveria ser reconsiderada.

# KMO
KMO(dados)
Kaiser-Meyer-Olkin factor adequacy
Call: KMO(r = dados)
Overall MSA =  0.62
MSA for each item = 
       JPMORGAN        CITIBANK      WELLSFARGO ROYALDUTCHSHELL      EXXONMOBIL 
           0.66            0.65            0.78            0.52            0.54 

O resultado nos mostra que os dados são razoáveis para a Análise Fatorial e nenhuma variável deve ser retirada.

A segunda verificação que devemos fazer é o teste de Esfericidade de Bartlett, que testa a hipótese nula de que a matriz de correlação é uma matriz identidade (ou seja, que as variáveis não se correlacionam). Para seguirmos com a Análise Fatorial devemos rejeitar essa hipótese nula.

Interpretação: Valor-p \(<\) 0.05, rejeitamos a hipótese nula, as correlações são significativas e é apropriado fazer análise fatorial; Valor-p \(\ge\) 0.05, não rejeitamos a hipótese, as variáveis não estão suficientemente correlacionadas e não devemos fazer a análise fatorial.

# Bartlett
cortest.bartlett(dados)
$chisq
[1] 173.3102

$p.value
[1] 5.720169e-32

$df
[1] 10

O p-valor foi significativo, ou seja, há evidências para se rejeitar a hipóstese nula. Seguimos com a Análise Fatorial.

Número de Fatores

Para determinar o número de fatores podemos usar dois métodos:

  • Regra de Kaiser
  • Scree plot
  • Paralel analysis (análise paralela)

A Regra de Kaiser sugere manter apenas os fatores com autovalores associados maiores que 1.

dados = scale(dados)
PCA = prcomp(dados)
autovalores = (PCA$sdev)^2
autovalores
[1] 2.4372731 1.4070127 0.5005127 0.4000316 0.2551699

De acordo com os valores obtidos para os autovalores e a regra de kaiser, o número de fatores indicados para o problema seria 2. Porém essa é uma regra um pouco ultrapassada, e podemos selecionar o número de fatores usando outros critérios.

O Scree Plot mostra os autovalores associados a cada fator (autovetores), em ordem decrescente. Cada ponto no gráfico representa um fator, o eixo \(x\) mostra o número do fator, o eixo \(y\) mostra o autovalor que representa a variância explicada por aquele fator.

A ideia é procurar um “cotovelo” no gráfico — um ponto em que os autovalores começam a diminuir lentamente, indicando que os fatores adicionais explicam pouca variância e são menos importantes.

plot(autovalores,type="b")

O gráfico indica que a partir de 3 fatores o ganho ao acrescentar mais um fator é muito pequeno.

Este mesmo processo pode ser feito usando a função fa.parallel do pacote psych. A mesma função retorna não somente o Scree Plot como também o resultado para se realizar a Análise Paralela.

# Scree Plot
fa.parallel(dados, fa = "fa", n.iter = 100, show.legend = FALSE)

Parallel analysis suggests that the number of factors =  2  and the number of components =  NA 

O gráfico gerado pela função mostra os autovalores reais em azul e autovalores médios gerados aleatoriamente por dados simulados em vermelho.

Enquanto o Scree Plot busca o “cotuvelo” do gráfico, a análise paralela seleciona os fatores que aparecem acima da linha aleatória (vermelha). A análise paralela então, para esse exemplo, sugere 2 fatores. Mas vale resaltar que o terceiro fator não está acima da linha vermelha por muito pouco.

De acordo com os três critérios de seleção de número de fatores, vamos mater a análise com 2 fatores.

Análise Fatorial

Uma vez determinado o número de fatores, os pesos podem ser estimados tanto pelo método de PCA quanto pelo método da Máxima Verossimilhança. Neste relatório serão apresentados as duas formas. Mas o método de máxima verossimilhança é mais recomendado.

Estimativa pelo PCA

A análise fatorial pode ser feita com a função pca(), que gera os componentes principais no R, ou até mesmo com a função eigen().

pca = prcomp(dados)
P = pca$rotation
sd = pca$sdev
sqrtD = diag(sd)
#pesos
L = P[,1:2]%*%sqrtD[1:2,1:2]
L
                      [,1]       [,2]
JPMORGAN        -0.7323218 -0.4365209
CITIBANK        -0.8311791 -0.2804859
WELLSFARGO      -0.7262022 -0.3738582
ROYALDUTCHSHELL -0.6047155  0.6939569
EXXONMOBIL      -0.5630885  0.7186401
#comunalidades 
comunalidades = rowSums(L^2)
comunalidades
       JPMORGAN        CITIBANK      WELLSFARGO ROYALDUTCHSHELL      EXXONMOBIL 
      0.7268458       0.7695311       0.6671396       0.8472571       0.8335122 
#variancia especifica
1 - rowSums(L^2)
       JPMORGAN        CITIBANK      WELLSFARGO ROYALDUTCHSHELL      EXXONMOBIL 
      0.2731542       0.2304689       0.3328604       0.1527429       0.1664878 
#proporção acumulada da variancia explicada
sum(sqrtD[1:2,1:2]^2)/sum(sqrtD^2)
[1] 0.7688572

Estimativa por Máxima Verossimilhança

O pacote psych realiza essa análise a partir da função fa(). A vantagem desta função é que o argumento fm nos permite estimar os pesos por máxima verissimilhança, basta selecionar fm = "ml". E esta é a forma mais adequada de se estimar os pesos. Veremos que os resultados não são iguais aqueles obtidos pela estimativa vindo do PCA.

fa_resultado = fa(
  dados, 
  nfactors = 2, 
  fm = "ml")
print(fa_resultado)
Factor Analysis using method =  ml
Call: fa(r = dados, nfactors = 2, fm = "ml")
Standardized loadings (pattern matrix) based upon correlation matrix
                  ML2   ML1   h2    u2 com
JPMORGAN         0.79 -0.10 0.58 0.417   1
CITIBANK         0.82  0.10 0.73 0.275   1
WELLSFARGO       0.68  0.00 0.46 0.542   1
ROYALDUTCHSHELL -0.01  1.00 1.00 0.005   1
EXXONMOBIL       0.03  0.68 0.47 0.530   1

                       ML2  ML1
SS loadings           1.75 1.48
Proportion Var        0.35 0.30
Cumulative Var        0.35 0.65
Proportion Explained  0.54 0.46
Cumulative Proportion 0.54 1.00

 With factor correlations of 
     ML2  ML1
ML2 1.00 0.28
ML1 0.28 1.00

Mean item complexity =  1
Test of the hypothesis that 2 factors are sufficient.

df null model =  10  with the objective function =  1.74 with Chi Square =  173.31
df of  the model are 1  and the objective function was  0.02 

The root mean square of the residuals (RMSR) is  0.02 
The df corrected root mean square of the residuals is  0.06 

The harmonic n.obs is  103 with the empirical chi square  0.78  with prob <  0.38 
The total n.obs was  103  with Likelihood Chi Square =  1.97  with prob <  0.16 

Tucker Lewis Index of factoring reliability =  0.939
RMSEA index =  0.097  and the 90 % confidence intervals are  0 0.302
BIC =  -2.66
Fit based upon off diagonal values = 1
Measures of factor score adequacy             
                                                   ML2  ML1
Correlation of (regression) scores with factors   0.91 1.00
Multiple R square of scores with factors          0.83 1.00
Minimum correlation of possible factor scores     0.66 0.99

A matriz de cargas fatoriais indica como cada variável se relaciona com os fatores.

# pesos / cargas
fa_resultado$loadings

Loadings:
                ML2    ML1   
JPMORGAN         0.786 -0.101
CITIBANK         0.819       
WELLSFARGO       0.678       
ROYALDUTCHSHELL         0.999
EXXONMOBIL              0.677

                 ML2   ML1
SS loadings    1.749 1.476
Proportion Var 0.350 0.295
Cumulative Var 0.350 0.645

Este resultado é uma matriz e aqui vale ressaltar que R omite automaticamente os valores muito pequenos (próximos de zero) para facilitar a leitura.

Podemos ver que JPMORGAN têm cargas nos dois fatores, mas a maior intensidade pe no primeiro fator. Já CITIBANK e WELLSFARGO apresentam cargas significativas apenas no primeiro fator. Por outro lado, ROYALDUTCHSHELL e EXXONMOBIL carregam fortemente representam o Fator 2.

Devemos agrupar as variáveis em função do fator onde têm maior carga. Pode ser dados nomes aos fatores conforme o conteúdo das variáveis, como por exemplo, bancos e energia: neste exemplo a análise fatorial agrupou no Fator 1 as ações de bancos (JPMORGAN, CITIBANK e WELLSFARGO) e no fator 2 as ações de energia/petróleo (ROYALDUTCHSHELL e EXXONMOBIL).

#comunalidades
fa_resultado$communalities
       JPMORGAN        CITIBANK      WELLSFARGO ROYALDUTCHSHELL      EXXONMOBIL 
      0.5834626       0.7253098       0.4579762       0.9950000       0.4701568 
#variancia especifica
fa_resultado$uniquenesses
       JPMORGAN        CITIBANK      WELLSFARGO ROYALDUTCHSHELL      EXXONMOBIL 
     0.41653750      0.27469024      0.54202352      0.00499844      0.52984315 

As comunalidades indicam a proporção da variância de cada variável que é explicada pelos fatores do modelo. As variância específicas (unicidades) indicam a parte da variância da variável que não é explicada pelos fatores. A comunalidade e a variância específica são complementares.

Visualização

Em uma análise fatorial pode ser interessante e informativo plotar os pontos (variáveis ou indivíduos) nas coordenadas dos fatores. Isso ajuda a visualizar a estrutura latente dos dados de forma clara.

Gráfico de Cargas Fatoriais (Variáveis no plano F1 × F2)

L <- unclass(fa_resultado$loadings)
plot(L[,1], L[,2],
     xlim = c(-1, 1), ylim = c(-1, 1),
     xlab = "Fator 1", ylab = "Fator 2",
     main = "Cargas Fatoriais",
     pch = 19, col = "blue")
# Adiciona rótulos
text(L[,1], L[,2], labels = rownames(L), pos = 1)
# Eixos centrais
abline(h = 0, v = 0, lty = 2)

Este gráfico mostra o padrão encontrado pelo modelo para as variáveis. No caso, o Fator 1 destaca as ações de banco enquanto o vator 2 as ações de energia.

Gráfico dos Scores Fatoriais (Indivíduos no plano F1 × F2)

scores <- fa_resultado$scores
x <- scores[, 1]
y <- scores[, 2]
plot(x, y,
     xlab = "Fator 1", ylab = "Fator 2",
     main = "Indivíduos no Espaço Fatorial",
     pch = 20, col = "darkgreen")
abline(h = 0, v = 0, lty = 2)

Neste gráfico cada ponto representa uma linha da base. Para o exemplo em questão, cada ponto representa um dia de observação da valorização das ações. O Fator 1 indica a valorização das ações de banco enquanto o Fator 2 a valorização das ações de energia. Os pontos mais à direita são aqueles que indicam dias com valorização das ações de banco. Os pontos acima do plano são aqueles que representam dias com valorização das ações de energia.

Vejamos alguns exemplos.

plot(x, y,
     xlab = "Fator 1", ylab = "Fator 2",
     main = "Indivíduos no Espaço Fatorial",
     pch = 20, col = "darkgreen")
abline(h = 0, v = 0, lty = 2)
texto = rep("",length(x))
texto[c(94,63,41,93,96)] = c("94","63","41","93","96")
text(x = x,y = y-0.1,labels = texto,pos = 3)

A observação de número 94 (canto superior à esquerda) representa um dia em que houve alta tanto nas ações de banco quanto nas ações de energia.

A observação de número 63 (canto inferior à direita) representa um dia em que tanto as ações de banco quanto de energia desvalorizaram.

A observação de número 41 (lado esquerdo perto do eixo x) representa um dia em que houve baixa das ações de energia e as ações de banco ficaram com valorização média.

A observação de número 93 (abaixo do gráfico perto do eixo y) representa um dia em que houve baixa nas ações de banco e as ações de energia ficaram com valorização média.

A observação de número 96 (lado esquerdo e abaixo) representa um dia em que houve alta nas ações de banco e baixa nas ações de energia.

Os pontos perto da origem representam os dias com valorização média tanto para as ações de banco quanto para as ações de energia.

Conclusão

A análise fatorial com dois fatores revelou uma estrutura latente coerente com a natureza setorial das ações analisadas. O primeiro fator está fortemente associado a empresas do setor bancário, enquanto o segundo fator representa predominantemente ações do setor de energia. Essa separação indica que os rendimentos das ações podem ser explicados, em grande parte, por influências comuns dentro de seus respectivos setores.

Os resultados reforçam a importância da segmentação por setor na modelagem e interpretação de retornos financeiros, sendo útil para estratégias de diversificação e gestão de risco em carteiras de investimento.