---
title: "ProcMod Package"
author: "Eric Coissac & Christelle Gonindard-Melodelima"
date: "`r Sys.Date()`"
output: 
  rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Vignette Title}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
library(ProcMod)
knitr::opts_knit$set(
  collapse = TRUE,
  comment = "#>",
  root.dir = system.file("extdata", package="ProcMod")
)
```

## Mathematic principles

## Estimation des coefficients lors d'une régression linéaire multiple (2 variables)


$$ \hat{y}=a_1 x_1 + a_2  x_2 + b$$

On cherche à minimiser l'erreur commise entre la prédiction et la vraie valeur (méthode des moindres carrés)

$$
\left\{
  \begin{array}{rcr}
   \sum_i{(y_i- \hat{y_i})^2}=0 \\
 \sum_i{(y_i- (a_1 x_{1,i} + a_2  x_{2,i} + b))^2}=0
  \end{array}
\right.
$$
Pour trouver les paramètres qui minimise cette fonction, on calcule les trois dérivées partielles et on les annule :

$$
\left\{
  \begin{array}{rcr}
   -2 \sum_i{x_{1,i}(y_i- a_1 x_{1,i} + a_2  x_{2,i} + b)}=0 \\
 -2 \sum_i{x_{2,i}(y_i- a_1 x_{1,i} + a_2  x_{2,i} + b)}=0 \\
 -2 \sum_i{(y_i- a_1 x_{1,i} + a_2  x_{2,i} + b)}=0
  \end{array}
\right.
$$

 A partir de la dernière équation, on obtient :
 
$$
 \overline{y}-a_1\overline{x_1}-a_2\overline{x_2}-b=0
 \\
 \Leftrightarrow \hat{b}=\overline{y}-a_1\overline{x_1}-a_2\overline{x_2}
$$
 
 
En remplaçant dans la première équation on obtient :

$$
\frac{\sum_i{x_{1,i}y_i}}{n}-a_1\frac{\sum_i{x_{1,i}^2}}{n}-a_2\frac{\sum_i{x_{1,i}x_{2,i}}}{n}-b\frac{\sum_i{x_{1,i}}}{n}=0
\\
\Leftrightarrow
\frac{\sum_i{x_{1,i}y_i}}{n}-a_1\frac{\sum_i{x_{1,i}^2}}{n}-a_2\frac{\sum_i{x_{1,i}x_{2,i}}}{n}-(\overline{y}-a_1\overline{x_1}-a_2\overline{x_2}) \overline{x_1}=0
\\
\Leftrightarrow
\frac{\sum_i{x_{1,i}y_i}}{n}-a_1\frac{\sum_i{x_{1,i}^2}}{n}-a_2\frac{\sum_i{x_{1,i}x_{2,i}}}{n}-(\overline{y}-a_1\overline{x_1}-a_2\overline{x_2} ) \overline{x_1}=0
\\
\Leftrightarrow
S_{xy}-a_1S^{2}_{x_{1}}-a_2S_{x_1x_2}=0
\\
\Leftrightarrow
\hat{a}_1=\frac{S_{x_1y}-a_2S_{x_1x_2}}{S^{2}_{x_{1}}}
$$
De la même manière, on obtient : 

$$
\hat{a}_2=\frac{S_{x_2y}-a_1S_{x_1x_2}}{S^{2}_{x_{2}}}
$$


$$
\hat{a}_1=\frac{S_{x_1y}-\frac{S_{x_2y}-a_1S_{x_1x_2}}{S^{2}_{x_{2}}}S_{x_1x_2}}{S^{2}_{x_{1}}}
$$


$$
\hat{a}_1-\hat{a}_1\frac{S^2_{x_1x_2}}
                     {S^2_{x_2}S^2_{x_1}}=\frac{S_{x_1y}}
               {S^2_{x_1}}
               -\frac{S_{x_1x_2}S_{x_2y}}
                     {S^2_{x_2}S^2_{x_1}}
$$

$$
\hat{a}_1(1-\frac{S^2_{x_1x_2}}
                     {S^2_{x_2}S^2_{x_1}})=\frac{S_{x_1y}}
               {S^2_{x_1}}
               -\frac{S_{x_1x_2}S_{x_2y}}
                     {S^2_{x_2}S^2_{x_1}}
$$

$$
\hat{a}_1\frac{S^2_{x_2}S^2_{x_1}-S^2_{x_1x_2}}
               {S^2_{x_2}S^2_{x_1}}=
          \frac{S_{x_1y}}
               {S^2_{x_1}}
               -\frac{S_{x_1x_2}S_{x_2y}}
                     {S^2_{x_2}S^2_{x_1}}
$$

$$
\hat{a}_1\frac{S^2_{x_2}S^2_{x_1}-S^2_{x_1x_2}}
               {S^2_{x_2}S^2_{x_1}}=
          \frac{S_{x_1y}S^2_{x_2}}
               {S^2_{x_1}S^2_{x_2}}
               -\frac{S_{x_1x_2}S_{x_2y}}
                     {S^2_{x_2}S^2_{x_1}}
$$

$$
\hat{a}_1 
               =
          \frac{S_{x_1y}S^2_{x_2}
               -S_{x_1x_2}S_{x_2y}}
                     {S^2_{x_2}S^2_{x_1}-S^2_{x_1x_2}}
$$

D'un point de vue matricielle, les coefficients des pentes peuvent s'écrire à partir des matrices de covariances des variables explicatives (X) et des covariances entre la matrice explicative (X) et et de la variable à expliquer Y: 

Soit $\tilde{\theta}(y)$ l'estimation des différentes paramètres de la régression multiple : 
dans notre cas :
$$
\tilde{\theta}(y) = (\hat a_1, \hat a_2)
$$

En généralisant : 
$$
\tilde{\theta}(y) = (X'X)^{-1}X'Y
$$

## Calcul matriciel : calculs de parts de variances expliquées d'un tableau Y à partir d'un  tableau X explicatif

Soit Y la matrice à expliquer et X la matrice explicative.
Par procuste on a trois opérations : 

* translation (revient à aligner les barycentres : centrer )

* échelle : homothétie

*  rotation trouver l'angle qui minimise : méthode des moindres carrés


Seule contrainte de la méthode, la rotation doit être effectuée en dernier.


On cherche : $$ Min|Y-(1c'+\rho X A)| $$

On se retrouve à minimiser comme en relation linéaire l'écart entre X notre tableau de données explicative et la matrice Y (qui représente l'approximation en régression linéaire) :
$$1c'+\rho X A $$


avec $c'$ translation (centrage), $\rho$ échelle (normalisation), $A$ rotation

D'un point de vue matriciel : il faut que A'A=I orthogonal, diag(A'A)=1

Les matrices centrées de X et Y sont notées :
$$\tilde{Y}, \tilde{X}$$ 

Décomposition en valeur singulière : avec U'U=V'V=I
$$\tilde{Y}' \tilde{X} = U \Lambda V'$$
La matrice de rotation est donc estimée par : $$\hat{A}=VU'$$

Paramètre d'échelle qui correspond à c dans procruste : 
$$\hat{\rho}=\frac{trace(\hat{A}\tilde{Y}'\tilde{X})}{trace(\tilde{Y}'\tilde{X})}$$

Si on fait l'analogie avec la fonction programmée dans procrustre (équivalence : translation <=> b, échelle <=> c et rotation A) :

$$ 
      Xrot = \hat{\rho} X A \\
      b = \overline{Y}-\hat{\rho}\overline{X} A
$$

Si la translation n'a pas encore été faite, on a : 

$$
Xrot = 1c'+ \hat{\rho} X A
\\
     b = \overline{Y}-\hat{\rho}\overline{X} A
$$

Xrot est la nouvelle estimation de X qui a été transformé pour "être représenté dans la même base" que Y

Et du coup la différence entre Xrot et Y représente la part non expliquée du tableau Y par X 

$$
\sum(Y-X_{rot})^2 = SRC_{residuel}
$$


## Calcul matriciel : calculs de parts de variances expliquées d'un tableau Y à partir de deux  tableaux X1 et X2 explicatifs


Soit Y la matrice à expliquer, X1 et X2 deux matrices explicatives.
Par procuste on a trois opérations : 

* translation (revient à aligner les barycentres : centrer )

* échelle : homothétie

*  rotation trouver l'angle qui minimise : méthode des moindres carrés


Seule contrainte de la méthode, la rotation doit être effectuée en dernier.


On cherche : $$ Min|Y-[(1c_1'+\rho_1 X_1 A_1)+(1c_2'+\rho_2 X_2 A_2)]| $$

On se retrouve à minimiser comme en relation linéaire l'écart entre X1 et X2 nos tableaux de données explicatives et la matrice Y (qui représente l'approximation en régression linéaire) :
$$(1c_1'+\rho_1 X_1 A_1)+(1c_2'+\rho_2 X_2 A_2) $$



avec $c_1'$ et $c_2'$ translation (centrage), $\rho1$ et $\rho_2$ échelle (normalisation), $A_1$ et $A_2$ rotation

D'un point de vue matriciel, les matrices de rotations doivent vérifier les conditions suivantes : A'A=I orthogonal, diag(A'A)=1

Les matrices centrées sont notées :
$$\tilde{Y}, \tilde{X_1}, \tilde{X_2}$$ 

Décomposition en valeur singulière avec :
$$ 
U_1'U_1 = V_1'V_1 = I
\\
   U_2'U_2 = V_2'V_2 = I
$$
$$ 
\tilde{Y}' \tilde{X_1} = U_1 \Lambda V_1'
\\
\tilde{Y}' \tilde{X_2} = U_2 \Lambda V_2'
$$
La matrice de rotation est donc estimée par : 
$$
\hat{A_1} = V_1 U_1'
\\
\hat{A_2} = V_2 U_2'
$$

Paramètre d'échelle qui correspond à c dans procruste : 
$$
\hat{\rho_1} = \frac{trace(\hat{A_1}\tilde{Y}'\tilde{X_1})}{trace(\tilde{Y}'\tilde{X_1})}
\\
\hat{\rho_2} = \frac{trace(\hat{A_2}\tilde{Y}'\tilde{X_2})}{trace(\tilde{Y}'\tilde{X_2})}
$$

Si on fait l'analogie avec la fonction programmée dans procrustre (équivalence : translation <=> b, échelle <=> c et rotation A) :

$$ 
X_1rot = \hat{\rho_1} X_1 A_1
\\
X_2rot = \hat{\rho_2} X_2 A_2
\\
b = \overline{Y}-\hat{\rho_1}\overline{X_1} A_1 -\hat{\rho_2}\overline{X_2} A_2
$$

Si la translation n'a pas encore été faite, on a : 

$$ 
X_1rot = 1c_1'+ \hat{\rho_1} X_1 A_1
\\
X_2rot = 1c_2'+ \hat{\rho_2} X_2 A_2
\\
b = \overline{Y}-\hat{\rho_1}\overline{X_1} A_1 -\hat{\rho_2}\overline{X_2} A_2
$$


X1rot et X2 rot sont les nouvelles estimations de X1 et X2 qui ont été transformé pour "être représenté dans la même base" que Y.





avec $c'$ translation (centrage), $\rho$ échelle (normalisation), $A$ rotation

D'un point de vue matriciel : il faut que A'A=I orthogonal, diag(A'A)=1

Les matrices centrées de X et Y sont notées :
$$\tilde{Y}, \tilde{X}$$ 

Décomposition en valeur singulière : avec U'U=V'V=I
$$\tilde{X}' \tilde{Y}=U \Lambda V'$$
La matrice de rotation est donc estimée par : $$\hat{A}=VU'$$

Paramètre d'échelle qui correspond à c dans procruste : 
$$\hat{\rho}=\frac{trace(\hat{A}\tilde{X}'\tilde{Y})}{trace(\tilde{Y}'\tilde{Y})}$$

Si on fait l'analogie avec la fonction programmée dans procrustre (équivalence : translation <=> b, échelle <=> c et rotation A) :

$$
Yrot=\hat{\rho} Y A
\\
b=\overline{X}-\hat{\rho}\overline{Y} A
$$

? j'aurai plus tôt écrit, la translation a déjà du être faite dans procruste avant cette étape??

$$
Yrot=1c'+ \hat{\rho} Y A
\\
b=\overline{X}-\hat{\rho}\overline{Y} A
$$

? Yrot est la nouvelle estimation de Y qui a été transformé pour "être représenté dans la même base" que X. ???

Et du coup la différence entre X et Yrot représente la part non expliquée par Y du tableau de données X 

$$
\sum(X-Y_{rot})^2=SRC_{residuel}
$$



## ProcMod usage

### The procmd.frame data structure

```{r}
A = matrix(1:6,nrow=3)
B = matrix(1:9,nrow=3)
C = matrix(1:12,nrow=3)

pf = procmod.frame(A,B,D=C, 
                   row.names = c('x','y','z'))

pf
```


### Build a model

#### Prepare the data

Three datasets are used

```{r}
euk = read.csv("australia.euk.reads.plot.csv",
               head=TRUE,
               row.names = 1)

bac = read.csv("australia.bac.reads.plot.csv",
               head=TRUE,
               row.names = 1)

env = read.csv("biogegraphy_and_environment.csv",
               head=TRUE,
               row.names = 1)
```

Only numerical environmental variables are kept.

```{r}
env=env[,lapply(env,class)=="numeric"]

geovar = which(colnames(env) %in% c('Latitude','Longitude'))
soilvar= which(colnames(env) %in% c("KLg",  "pH", "AlLg", 
                                    "FeLg", "PLg", "SLg", 
                                    "CaLg", "MgLg",  "MnLg", 
                                    "CNratio", "CLg", "NLg"))
climvar= which(colnames(env) %in% c("Aspect", "TempSeasonality", 
                                    "MaxMonTemp", "Elevation", 
                                    "MeanMonTempRange", "AnnMeanTemp",  
                                    "Isothemality"))

geo    = env[,geovar]
```

Environmental data are centered and reduced

```{r}
env = scale(env,scale = TRUE)
soil   = env[,soilvar]
climat = env[,climvar]
```

Eukaryote and bacterial data are arranged in the same order than environmental data.

```{r}
euk=euk[rownames(env),]
bac=bac[rownames(env),]
```

Relative frequency tables for Eukaryota and Bacteria are root square transforms which corresponds to Hellinger transformation.

```{r}
euk=sqrt(euk)
bac=sqrt(bac)
```


Using the `vegan` package the Jaccard distance is computed among the sites according to the Eukaryota and Bacteria markers.

```{r}
library(vegan)
euk.dist=vegdist(euk,method = "jaccard")
bac.dist=vegdist(bac,method = "jaccard")
```

Using the `ade4` package a principal coordinate analysis is done to place the sites in a cartesian space reflecting the distances among the sites.

```{r}
library(ade4)
euk.pco =dudi.pco(euk.dist,full = TRUE)
bac.pco =dudi.pco(bac.dist,full = TRUE)
```

```{r}
mat.scale = function(mat) {
  cmat = scale(mat,scale = FALSE)
  mat.sd = sqrt(sum(cmat^2))
  return (cmat/mat.sd)
} 
```


Coordinates of the sites are extracted from the PCoA analysis

```{r}
euk.pco.li = euk.pco$li
bac.pco.li = bac.pco$li
```

```{r, fig.show='hold'}
plot(euk.pco.li[,1:2],cex=0,
     main="Eukariota")
text(euk.pco.li[,1:2],
     labels = rownames(euk.pco.li),
     cex=0.4)

plot(bac.pco.li[,1:2],cex=0,
     main="Bacteria")
text(bac.pco.li[,1:2],
     labels = rownames(bac.pco.li),
     cex=0.4)
```

The environmental variable are transformed using a Principal Component Analysis.

```{r}
env.pca = dudi.pca(env,scannf = FALSE,nf=nrow(env)-1)
env.pca.li = env.pca$li
plot(env.pca.li[,1:2],cex=0,
     main="Environmental data")
text(env.pca.li[,1:2],
     labels = rownames(env.pca.li),
     cex=0.4)

soil.pca = dudi.pca(soil,scannf = FALSE,nf=nrow(soil)-1)
soil.pca.li = soil.pca$li

climat.pca = dudi.pca(climat,scannf = FALSE,nf=nrow(climat)-1)
climat.pca.li = climat.pca$li

geo.pco = dudi.pco(dist(geo),full = TRUE)
geo.pco.li = geo.pco$li

```


```{r}
dh = matrix(1,nrow = 62,ncol=62)
diag(dh)=0
dh=as.dist(dh)
dh.pco =dudi.pco(dh,full = TRUE)
dh.pco.li = dh.pco$li
```

### Using the package to analyse relationship among the tables

First load the library

```{r}
library(ProcMod)
```

#### Computing the variance/covariance matix

```{r}
data = procmod.frame(euk=euk.pco.li,bac=bac.pco.li,
                     climat=climat.pca.li,soil=soil.pca.li,
                     geo=geo.pco.li,hist=dh.pco.li)

vars = mvar(data)
```

```{r echo=FALSE}
knitr::kable(vars)
```


#### Computing the correlation matix

```{r}
cors = mcor(data)
```

```{r echo=FALSE}
knitr::kable(cors)
```

#### Building the multiprocruste model

```{r}
euk.pm = pm(euk ~ soil + climat +  geo + hist,data=data)
euk.pm
```

results can be ploted like a classical prooruste result

```{r}
plot(euk.pm)
```

```{r}
W=1/rowSums(euk.pm$residuals^2)
W=W/max(W)
euk.pm.w = pm(euk ~ soil + climat +  geo + hist,data=data,weights = W)
euk.pm.w

```

```{r}
plot(euk.pm.w)
```

finaly the analysis of the variance corresponding to this model

```{r}
euk.anova = anova(euk.pm)
euk.anova
```

Partition of the variance among the factors

```{r}
partition = euk.anova[,"Sum Sq"]/sum(euk.anova[,"Sum Sq"])
names(partition)=rownames(euk.anova)
partition
```
```{r}
euk.anova.w = anova(euk.pm.w)
euk.anova.w
```
```{r}
partition = euk.anova.w[,"Sum Sq"]/sum(euk.anova.w[,"Sum Sq"])
names(partition)=rownames(euk.anova.w)
partition
```


```{r}
bac.pm = pm(bac ~ soil + climat +  geo + hist,data=data)
bac.pm
```

```{r}
plot(bac.pm)
```

```{r}
bac.anova = anova(bac.pm)
bac.anova
```

```{r}
partition = bac.anova[,"Sum Sq"]/sum(bac.anova[,"Sum Sq"])
names(partition)=rownames(bac.anova)
partition
```

```{r}
soil.pm = pm( hist ~ bac + euk + climat +  geo + soil,data=data)
soil.pm
```

```{r}
plot(soil.pm)
```

```{r}
soil.anova = anova(soil.pm)
soil.anova
```


```{r}
histoire = mat.scale(as.matrix(dh))
bacterie = mat.scale(as.matrix(bac.dist))
eukariote = mat.scale(as.matrix(euk.dist))
pm(eukariote ~ bacterie)
cor(bac.dist,euk.dist)
```

