---
title: "PCA e EFA (notebook 3)"
author: "Dario Trevisan"
date: "08/10/2025"
output:
  html_notebook:
    toc: true
    toc_depth: 3
    toc_float: true
    theme: readable
    df_print: paged
    download_handler: true
  html_document:
    toc: true
    toc_depth: '3'
    df_print: paged
subtitle: "Statistica II - 750AA"
---




## Introduzione
In questo notebook, esploreremo sia l'Analisi delle Componenti Principali (PCA) che l'Analisi Fattoriale Esplorativa (EFA) su diversi dataset: alcuni generati, altri pre-caricati di R (come ``iris`` e ``mtcars``), e un dataset reale (ANSES-CIQUAL food composition table
2020).

```{r}
# Alcuni pacchetti che useremo: se non presenti installatele con il comando install.packages()
library(readxl)
library(tidyr, stringr)
library(ggplot2, ggcorrplot)
library(corrplot)
library(ggfortify)
```

## Esempi con dataset generati

Come nel notebook precedente, generiamo dei dati partendo da campioni gaussiani di medie e deviazioni standard specificate.

```{r}
# Impostare il seed per l'esatta riproduzione
#set.seed(123)

# Specifichiamo la taglia n del campione generato e il numero di features d

n <- 100
d <- 5

data_gen <- data.frame(rnorm(n))

# Etichette per le colonne
names_data_gen <- print(paste0("feature_", as.character(1)))

for( i in 2:d ){
  data_gen <- cbind( data_gen,  rnorm(n, mean=0, sd=1))
  names_data_gen <- c(names_data_gen, print(paste0("feature_", as.character(i))))
}

colnames(data_gen) <- names_data_gen

head(data_gen)

pairs(data_gen)

```

In questo dataset la varianza campionaria dovrebbe essere all'incirca diagonale con degli $1$ sulla diagonale -- perché le colonne sono state generate in modo *indipendente* e abbiamo specificato la deviazione standard teorica ``sd=1``.

I comandi per la varianza, covarianza e correlazione sono rispettivamente ``var()``, ``cov()`` e  ``cor()``.

```{r}
# var() calcola la matrice delle covarianze completa

var_data_gen <- var(data_gen)
var_data_gen
```

```{r}
# cor() calcola la matrice delle correlazioni

cor_data_gen <- cor(data_gen)
cor_data_gen
```

Con ``cov()`` e ``cor()`` è possibile anche calcolare covarianze tra coppie di data frames.

```{r}

cov(data_gen[1:2], data_gen[3:4])
cor(data_gen[-3], data_gen[3])
```

Per visualizzare le correlazioni mediante una mappa di calore possiamo usare il pacchetto ``corrplot`` oppure ``ggcorrplot`` (che estende ``ggplot2``).

```{r}
# installare corrplot se non è già presente
library(corrplot)

# plot di base
corrplot(cor_data_gen)
```

Ci sono moltissime opzioni per migliorare il grafico (leggere l'help per informazioni).

```{r}
corrplot(cor_data_gen, method="pie", type="lower", diag=FALSE, number.cex=1, number.digits = 2, title="Dataset generato (features indipendenti)")
```

Similmente, usando ``ggcorrplot`` si producono grafici con ggplot.

```{r}
# installare il pacchetto se non presente
library(ggcorrplot)

ggcorrplot(cor_data_gen,  type="upper", title="Dataset generato (features indipendenti)", hc.order = TRUE)
```


### Dataset con correlazioni

Le matrici trovate di correlazione sono poco interessanti, perché il dataset non presenta associazioni interessanti tra le varie features. Per introdurre artificialmente queste correlazioni, trasformiamo le features con una mappa opportuna.

```{r}
# Aggiungiamo una correlazione tra le variabili.
# Costruiamo una matrice casuale con valori -1, 0 o 1

entrate_matrice <- sample(c(-1,0,1), d*d, replace=TRUE)

A <- matrix(entrate_matrice, nrow=d, ncol=d)

# visualizziamo la matrice

A

# Moltiplichiamo il data frame (trasformato in matrice) per la matrice

data_gen_A <- data.frame( as.matrix.data.frame(data_gen) %*% A)

colnames(data_gen_A) <- names_data_gen

head(data_gen_A)

plot(data_gen_A)


```
In questo caso il correlogramma è più interessante
```{r}
cor_data_gen_A <- cor(data_gen_A)

ggcorrplot(cor_data_gen_A, method="square", type="upper", title="Dataset generato (features dipendenti)", hc.order = FALSE, lab=TRUE)
```

Dalla teoria sappiamo che $\operatorname{var}(xA) = A^T \operatorname{var}(x) A \approx A^T A$ essendo $\operatorname{var}(x)\approx I_{d\times d}$. Verifichiamolo numericamente. Calcoliamo la varianza campionaria.

```{r}

var(data_gen_A)
```
 
Per calcolare la trasposta di una matrice usiamo la funzione ``t()``.
```{r}
cov_A_teorica <- t(A) %*% A
cov_A_teorica
```

### PCA sul Dataset Generato

Per eseguire l'analisi delle componenti principali, possiamo usare il comando ``prcomp()`` (consigliato) oppure il comando  ``princomp()``. Si veda <https://cran.r-project.org/web/packages/LearnPCA/vignettes/Vig_07_Functions_PCA.pdf> per una discussione delle differenze. 

È fortemente consigliato per la PCA di standardizzare i dati. Possiamo farlo prima con il comando ``scale()``

```{r}

# usiamo direttamente il dataset generato con correlazioni indotte da A
data_gen <- data_gen_A

# standardizziamo
data_gen_standard <- scale(data_gen, center=TRUE, scale=TRUE)

# Notiamo che la media è nulla per ciascuna feature
summary(data_gen_standard)

# Notiamo che la varianza coincide con la correlazione
var(data_gen_standard)
cor(data_gen_standard)

```

A questo punto possiamo usare il comando ``prcomp()``.


```{r}
pca_gen <- prcomp(data_gen_standard)
summary(pca_gen)

```

Oppure è equivalente usare l'opzione ``scale.TRUE`` sul data frame originale.

```{r}

pca_gen <- prcomp(data_gen, scale. = TRUE)
summary(pca_gen)
```

Leggiamo dall'output di ``summary()`` la deviazione standard ($\sqrt{\lambda_j}$) per ciascuna componente principale, oltre alla proporzione di varianza _spiegata_ e la proporzione cumulativa. Possiamo visualizzarli tramite dei plot. Cominciamo con lo _scree plot_.


```{r}

variances_pca_gen <- (pca_gen$sdev)**2

# uno scree plot con il comando plot
plot(variances_pca_gen, type='l')
points(variances_pca_gen)

# uno scree plot con ggplot2

scree_data <- data.frame(PC = 1:d, Variance = variances_pca_gen)
ggplot(scree_data, aes(x = PC, y = Variance)) +
  geom_line() +
  geom_point() +
  labs(title = "Scree Plot: dataset generato", x = "Componenti Principali", y = "Autovalori")+
  scale_x_continuous(label = ~ scales::comma(.x, accuracy = 1))

```

Presentiamo il plot della varianza cumulata.


```{r}

# calcoliamo la percentuale di varianza cumulativa

cum_var <- data.frame(PC = 1:d, Variance = cumsum(variances_pca_gen)/sum(variances_pca_gen))

# plot di base
plot(cum_var, type='l')
points(cum_var)
abline(h=0.95, col="red", lty=3)

# stesso plot ma con ggplot2

ggplot(cum_var, aes(x = PC, y = Variance)) +
  geom_line() +
  geom_point() +
  labs(title = "Varianza cumulata: dataset generato (indipendenti)", x = "Componenti Principali", y = "percentuale di varianza")+
  scale_x_continuous(label = ~ scales::comma(.x, accuracy = 1)) +
  geom_hline(yintercept = 0.95, linetype="dashed",  color = "red", size=1)

```

Presentiamo infine il _biplot_ in cui sia gli scores che i loadings vengono rappresentati sullo stesso piano. Il comando di base è ``biplot()``. Per grafici più personalizzabili e chiari consigliamo di usare ``autoplot()`` dal pacchetto ``ggfortify``.


```{r}
# Biplot di base su esito di prcomp
biplot(pca_gen, main = "Biplot PCA dataset generato")

# installare ggfortify se non presente
library(ggfortify)

# installare anche ggrepel per evitare sovrapposizioni tra le etichette
library(ggrepel)

# autoplot provvede in automatico a presentare il biplot in modo esteticamente equilibrato

autoplot(pca_gen, data = data_gen, x=2, y=3, # selezionare eventualmente altre componenti principali ad esempio x=2, y=3
         label=FALSE, loadings = TRUE, loadings.label = TRUE, loadings.label.colour="blue", loadings.label.size = 3, loadings.label.repel = TRUE, main = "Biplot PCA dataset generato")
```
Osserviamo la matrice delle rotazioni (detta anche dei _loadings_).

```{r}
pca_gen$rotation
```

### EFA sul Dataset Generato

Passiamo ora all'Analisi Fattoriale Esplorativa (EFA). Anche qui abbiamo diversi comandi: ``factanal()`` del pacchetto ``stats`` (di base) e ``fa()`` del pacchetto ``psych``, più avanzato.

```{r}
# cerchiamo un solo fattore (che potrebbe essere vicino alla PC1)

efa_gen <- factanal(data_gen, factors=2)

# library(psych)
# efa_gen<- fa(data_gen, fators=3)

summary(efa_gen)

```

Controlliamo in che misura l'equazione matriciale della EFA: $\operatorname{var}(x) = L^T L + \Psi$ è numericamente valida.

```{r}
cor(data_gen)

 efa_gen$loadings[1:d] %*% t(efa_gen$loadings[1:d]) +diag(efa_gen$uniquenesses, nrow=d, ncol=d)

```

Confrontiamo il vettore dei loadings con la prima componente principale riscalata per la sua deviazione standard.

```{r}
loading_PCA <- pca_gen$sdev[1]* pca_gen$rotation[,1]

print("Loadings PCA: ")
loading_PCA
print("Loadings EFA: ")
efa_gen$loadings[1:d]
```

**Esercizio**: effettuare una PCA su un dataset non standardizzato, verificare che le PC tendono a *catturare* le componenti che hanno varianza maggiore (invece di rilevare le correlazioni).

## Esempi con dataset precaricati

Cominciamo con il dataset ``iris``.

```{r}

head(iris)

summary(iris)

pairs(iris[-5], col=iris[,5])
```

Studiamo la correlazione.

```{r}
ggcorrplot(cor(iris[-5]), type="lower")
```
Vediamo una forte correlazione positiva tra le lunghezze, larghezze dei petali e lunghezza del sepalo, mentre una correlazione debole negativa tra queste e la larghezza del sepalo.

**Suggerimento**: alcuni grafici comuni (scatterplot, heatmap della correlazione) si possono condensare in uno solo, ed eseguire con comandi diretti del pacchetto ``GGally``.

```{r}
library(GGally)

ggpairs(iris[-5])

```


### PCA sul dataset Iris

```{r}

pca_iris <- prcomp(iris[-5], scale. = TRUE)
summary(pca_iris)

```
Notiamo che le prime due PC spiegano il $95\%$ della varianza.

```{r}

scree_data <- data.frame(PC = 1:4, Variance =pca_iris$sdev**2)
ggplot(scree_data, aes(x = PC, y = Variance)) +
  geom_line() +
  geom_point() +
  labs(title = "Scree Plot: dataset iris", x = "Componenti Principali", y = "Autovalori")+
  scale_x_continuous(label = ~ scales::comma(.x, accuracy = 1))
```

Mostriamo il biplot ed intepretiamo il risultato della PCA.
```{r}

autoplot(pca_iris, data = iris, colour="Species", x=1, y=2, # selezionare eventualmente altre componenti principali ad esempio x=2, y=3
         label=FALSE, loadings = TRUE, loadings.label = TRUE, loadings.label.colour="blue", loadings.label.repel=TRUE,
         loadings.label.size = 3, 
         main = "Biplot PCA dataset generato")

```
Il biplot mostra che la PC1 è associata alle tre variabili _petali_ e _lunghezza dei sepali_, mentre la PC2 è associata alla _larghezza dei sepali_. Vediamolo attraverso la matrice dei loadings.


```{r}
round(pca_iris$rotation[, 1:2], 2)
```

### EFA sul Dataset Iris

Possiamo eseguire la EFA sullo stesso dataset.

```{r}
library(psych)
efa_iris <- fa(iris[-5], nfactors = 2)

# Riassunto dei risultati: loadings
efa_iris$loadings

efa_iris$communalities
```
L'analisi rivela la stessa situazione: tre variabili possono essere espresse in termini del primo fattore, la rimanente tramite il secondo fattore.

### PCA sul dataset mtcars

Riprendiamo il dataset ``mtcars`` e studiamolo mediante PCA e poi EFA.

```{r}

head(mtcars)

# togliamo le features 8 e 9 perché non numeriche (sono indicatrici)

mtcars_num <- mtcars[-(8:9)]

cor_mtcars <- cor(mtcars_num)

ggcorrplot(cor_mtcars, method="square", type="upper", title="Dataset generato (features dipendenti)", hc.order = TRUE, lab=FALSE)

```
Riconosciamo due _blocchi_ di variabili correlate in senso opposto: il primo è _carb, wt, hp, cyl, disp_, _qsec,  mpg, drat, gear_.

Vediamo cosa evidenza la PCA.



```{r}
pca_mtcars <- prcomp(mtcars_num, scale. = TRUE)

# Riassunto dei risultati
summary(pca_mtcars)

# Scree plot

scree_mtcars <- data.frame(PC = 1:ncol(mtcars_num), Variance =pca_mtcars$sdev**2)

ggplot(scree_mtcars, aes(x = PC, y = Variance)) +
  geom_line() +
  geom_point() +
  labs(title = "Scree Plot: dataset mtcars", x = "Componenti Principali", y = "Autovalori")+
  scale_x_continuous(label = ~ scales::comma(.x, accuracy = 1))


```
Riconosciamo un *gomito* a $k=3$, mentre il criterio di Kaiser 
darebbe $k=2$. Il grafico della varianza spiegata cumulata darebbe $k=4$ (quasi $k=3$) per arrivare al $95\%$.

```{r}


cum_var <- data.frame(PC = 1:length(pca_mtcars$sdev), Variance = cumsum(pca_mtcars$sdev^2)/sum(pca_mtcars$sdev^2))

ggplot(cum_var, aes(x = PC, y = Variance)) +
  geom_line() +
  geom_point() +
  labs(title = "Varianza cumulata: dataset generato (indipendenti)", x = "Componenti Principali", y = "percentuale di varianza")+
  scale_x_continuous(label = ~ scales::comma(.x, accuracy = 1)) +
  geom_hline(yintercept = 0.95, linetype="dashed",  color = "red", size=1)
```

Visualizziamo i biplot per le PC1, PC2 e pure PC3.

```{r}


autoplot(pca_mtcars, data = mtcars, colour="cyl", x=1, y=2, # selezionare eventualmente altre componenti principali ad esempio x=2, y=3
         label=FALSE, loadings = TRUE, loadings.label = TRUE, label.size=3, shape=20,  loadings.label.colour="red", loadings.label.repel=TRUE, loadings.label.size = 4, 
         main = "Biplot PCA dataset mtcars")


```

Abbiamo quindi una PC 1 in cui i due gruppi di variabili sono ben separati. Visto l'allineamento di _mpg_ e _cyl_ sembrerebbe una feature legata al _consumo_. La PC 2 invece è più allineata con _gear_ e _qsec_, quindi più legata alle _prestazioni_ (accelerazione da ferma ecc.).

Possiamo confermare la nostra ipotesi visualizzando il plot degli scores relativi a PC1 e PC2 con i nomi dei modelli.

```{r}

autoplot(pca_mtcars, data = mtcars, colour="mpg", size="qsec", x=1, y=2,
         label=TRUE, label.repel=TRUE, loadings = FALSE, loadings.label = FALSE, label.size=3, shape=20,  loadings.label.colour="red", loadings.label.repel=TRUE, loadings.label.size = 4, 
         main = "Biplot PCA dataset mtcars")


```

Consideriamo anche la terza componente principale (plottiamo solo PC2 e PC3). Questa sembra essere anche legata al peso _wt_ e al numero di carburatori _carb_.

```{r}

autoplot(pca_mtcars, data = mtcars, colour="cyl", size="wt", x=2, y=3,
         label=FALSE, loadings = TRUE, loadings.label = TRUE, label.size=3, shape=20,  loadings.label.colour="red", loadings.label.repel=TRUE, loadings.label.size = 4, 
         main = "Biplot PCA dataset mtcars")


```


### EFA sul Dataset mtcars

Eseguiamo ora una EFA sullo stesso dataset.

```{r}
# Eseguiamo l'EFA
efa_mtcars <- factanal(mtcars_num, factors = 2)

# Riassunto dei risultati
print(efa_mtcars)
```


##  Un dataset reale



La tabella di composizione alimentare ANSES-CIQUAL, [disponibile in formato Excel](https://ciqual.anses.fr/cms/sites/default/files/inline-files/Table%20Ciqual%202020_ENG_2020%2007%2007.xls), è gestito dal CIQUAL all'interno dell'Osservatorio dell'Alimentazione, un'unità di ANSES (l'agenzia francese per la sicurezza alimentare, ambientale e della salute occupazionale). La sua missione è raccogliere, valutare e rendere disponibili i dati sulla composizione nutrizionale degli alimenti consumati in Francia. Questo file contiene la composizione di 3185 alimenti per 67 componenti, come carboidrati, zuccheri, proteine, grassi, vitamine e minerali, fornendo informazioni dettagliate per ogni 100 g della parte commestibile degli alimenti.

È importante notare che, in caso di valori mancanti, viene utilizzato un trattino al posto del numero, e tali valori non dovrebbero essere considerati come zero (*cosa che invece faremo per semplicità*). Inoltre, il termine _traccia_ viene utilizzato quando un componente è rilevato ma non può essere quantificato con precisione, oppure quando si stima che il contenuto di un alimento sia molto basso, ma non nullo. In questi casi, il contenuto medio viene pubblicato come _traccia_.

Con queste premesse, carichiamo il file dal formato Excel.

```{r}

library(readxl)

ciqual <- read_excel("datasets/Table Ciqual 2020_ENG_2020 07 07.xls", 
     col_types = c("skip", "skip", "skip", 
         "text", "text", "skip", "skip", "text", 
         "skip", "text", "text", "text", "text", 
         "text", "text", "text", "text", "text", 
         "text", "text", "text", "text", "text", 
         "text", "text", "text", "text", "text", 
         "text", "text", "text", "text", "text", 
         "text", "skip", "skip", "skip", "skip", 
         "skip", "skip", "skip", "skip", "skip", 
         "skip", "skip", "skip", "skip", "skip",
         "text", "text", "text", "text", "text", 
         "text", "text", "text", "text", "text", 
         "text", "text", "text", "text", "text", 
         "text", "text", "text", "text", "text", 
         "text", "text", "text", "text", "text", 
         "text", "text", "text"))

head(ciqual)

```


Ripuliamo il dataset rimuovendo caratteri non standard come righe, e i dati mancanti ecc.

```{r}


ciqual_tidy <- ciqual

ciqual_tidy[ciqual=="-"]<- "0"
ciqual_tidy[] <- lapply(ciqual_tidy, function(x) gsub("< ", "", x))
ciqual_tidy[] <- lapply(ciqual_tidy, function(x) gsub(",", ".", x))
ciqual_tidy[] <- lapply(ciqual_tidy, function(x) gsub("traces", "0", x))
ciqual_tidy$alim_nom_eng <- ciqual$alim_nom_eng

ciqual_tidy[-(1:3)] <- lapply(ciqual_tidy[-(1:3)], function(x) as.numeric(x))
ciqual_tidy <- drop_na(ciqual_tidy)
names_ciqual_short <- substr(colnames(ciqual_tidy), 1, 10)

head(ciqual_tidy)

```

Selezioniamo alcune colonne per effettuare PCA e EFA.

```{r}

c_select <- c(1, 7:9, 11:14, 17, 30, 40, 41)

# oppure selezioniamo tutte le colonne eccetto le prime 3

#c_select <- c(-(2:3))
 
ciqual_reduced <- ciqual_tidy[c_select]


colnames(ciqual_reduced)<- names_ciqual_short[c_select]

cor_ciqual <- cor(ciqual_reduced[-1])

ggcorrplot(cor_ciqual, type="upper", hc.order=TRUE, lab=FALSE)

```

Notiamo una forte correlazione positiva tra carboidrati e zuccheri, tra grassi ed energia, tra sale e sodio, e una correlazione negativa (più o meno forte) tra l'acqua e tutto il resto.


### PCA su dataset reale

Passiamo alla PCA.

```{r}

pca_result <- prcomp(ciqual_reduced[-1], center=TRUE, scale.=TRUE)


# Riassunto dei risultati
summary(pca_result)

# Scree plot

scree_ciqual <- data.frame(PC = 1:ncol(ciqual_reduced[-1]), Variance =pca_result$sdev**2)

ggplot(scree_ciqual, aes(x = PC, y = Variance)) +
  geom_line() +
  geom_point() +
  labs(title = "Scree Plot: dataset CIQUAL", x = "Componenti Principali", y = "Autovalori")+
  scale_x_continuous(label = ~ scales::comma(.x, accuracy = 1))




```
Possiamo selezionare le prime tre componenti principali basandoci sul criterio di Kaiser e scree plot.


Osserviamo ora il biplot.

```{r}
autoplot(pca_result, data = ciqual_reduced, col="alim_grp_n",
         loadings = TRUE, loadings.label = TRUE, loadings.label.colour="black", loadings.label.repel=TRUE,
         loadings.label.size = 3, 
         main = "Biplot del Dataset ciqual reduced PC1-PC2")
```
La PC1 sembra essere legata alla presenza o meno di acqua e ai grassi e carboidrati. La PC2 invece distingue piuttosto se l'alimento è proteico/grasso/salato oppure ricco di zuccheri (dolce?). Visualizziamo solamente il plot degli scores senza i loadings.

```{r}
autoplot(pca_result, data = ciqual_reduced, col="alim_grp_n",
         loadings = FALSE, loadings.label = FALSE, 
         main = "Biplot del Dataset ciqual reduced PC1-PC2")

```

Quali sono gli alimenti classificati come _miscellaneous_?

```{r}

head(ciqual_tidy[ciqual_tidy$alim_grp_nom_eng =="miscellaneous", ])

```
Sono le salse: quindi PC2 potrebbe indicare un'asse _dolce vs salato_. Vediamo ora la PC3.


```{r}
autoplot(pca_result, data = ciqual_reduced, col="alim_grp_n", x=2, y=3,
         loadings = TRUE, loadings.label = TRUE, loadings.label.colour="black", loadings.label.repel=TRUE,
         loadings.label.size = 3, 
         main = "Biplot del sDataset ciqual reduced PC2-PC3")
```

La PC3 sembra distinguere tra contenuto di sale e grassi/proteine.

**Esercizo:**  In effetti le salse sono dei veri e propri _outliers_, anche perché stiamo confrontando gli indicatori nutrizionali per 100 g di prodotto. Ripetere tutta l'analisi delle componenti principali rimuovendo le righe corrispondenti al gruppo _miscellaneous_. I risultati si prestano a interepretazoni diverse?




### EFA su dataset reale


Eseguiamo infine l'analisi fattoriale esplorativa.


```{r}
# Eseguiamo l'EFA
efa_ciqual <- factanal(ciqual_reduced[-1], factors = 3)

# Riassunto dei risultati
print(efa_ciqual)
```
Troviamo 3 fattori: uno legato al sale/sodio, uno legato ai carboidrati/acqua, e un terzo legato all'energia/grassi/proteine. Ovviamente la varianza cumulata è ancora insufficiente (il test rifiuta l'ipotesi che 3 fattori siano sufficienti). Cosa accade se aumentiamo il numero di fattori latenti?

## Esercizi


1. Generare una matrice $A$ simmetrica e semidefinita positiva con 3 righe e 3 colonne. Implementare il calcolo della radice quarta di $A$, ovvero di una matrice $Q$ tale che $Q^4=A$.

2.Generare 100 coppie di dati Gaussiani che abbiano la bisettrice del primo quadrante come asse principale e varianza 9 lungo tale direzione. Dire quale deve essere l’altro asse principale.

3. Si generi una tabella di 3 colonne e 25 righe. Le prime due colonne siano Gaussiane (media e varianza a piacere), la terza colonna sia la somma delle prime due colonne più un piccolo rumore. Ottenere le varianze spiegate delle componenti principali della tabella, rappresentarle in un grafico illustrativo e visualizzare il grafico delle prime due componenti principali.

4. Generare un vettore Gaussiano di 5000 punti con componenti principali di varianze 9, 4 e 1 ed in modo che i suoi assi principali siano le bisettrici dei quadranti del piano xy e l’asse delle quote. Ottenere il grafico della proiezione dei punti sul piano xz.

5. Generare un campione Gaussiano quadri-dimensionale di numerosità 100, in modo che questo risulti approssimativamente bidimensionale e che la prima componente principale sia la somma delle prime due componenti.

6. Creare una tabella con 5 colonne e 350 righe, e popolarla di valori in modo che il biplot dell’analisi delle componenti principali per la tabella creata presenti alcune frecce molto corte.

7. Generare una tabella di dati in modo che, analizzata attraverso l’analisi delle componenti principali, riveli un accumulo di dati sul piano principale che però si rivela ingannevole se visto attraverso gli altri piani.

8. Considerare la tabella di dati iris. Studiare la corrispondente tabella ottenuta attraverso i logaritmi dei dati originari (ovvero, indagare rispetto a una dipendenza di tipo potenza tra i fattori).
  
  - Valutare l’opportunità di standardizzare la tabella ottenuta.
  
  - Ricavare l’analisi delle componenti principali per la nuova tabella di dati.
  
  - Verificare, colorando i punti rappresentati sui piani principali in accordo con la corrispondente specie, la collocazione dei dati in dipendenza dalla specie.

