From b76ca99bb81fa2fd6b97fbb8fec19f9bb352b46b Mon Sep 17 00:00:00 2001
From: Walmes Zeviani <walmes@ufpr.br>
Date: Wed, 4 Jul 2018 17:21:24 -0300
Subject: [PATCH] =?UTF-8?q?Conclui=20arquivo=20com=20exemplos=20de=20m?=
 =?UTF-8?q?=C3=A9todos=20intensivos.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 scripts/metodos-intensivos.Rmd | 237 +++++++++++++++++++++++----------
 1 file changed, 168 insertions(+), 69 deletions(-)

diff --git a/scripts/metodos-intensivos.Rmd b/scripts/metodos-intensivos.Rmd
index 3b29cd0..896c941 100644
--- a/scripts/metodos-intensivos.Rmd
+++ b/scripts/metodos-intensivos.Rmd
@@ -19,18 +19,44 @@ opts_chunk$set(cache = TRUE,
                message = FALSE)
 ```
 
+Esse documento contém exemplos de aplicação de métodos
+computacionalmente intensivos em problemas de inferência estatística.
+Tais problemas são tipicamente testes de hipóteses, estimação intervalar
+e estudo de propriedades de estimadores.  Os métodos exemplificados são:
+
+  * Testes de aleatorização
+  * Métodos Jackknife.
+  * Métodos bootstrap.
+  * Métodos Monte Carlo.
+
+As sessões a seguir estão dividas em exemplos.
+
 # Testes de aleatorização
 
 ## Uma senhora toma chá
 
+Visite
+
+  * <https://en.wikipedia.org/wiki/Lady_tasting_tea>.
+  * Série de vídeos.
+    * <https://www.youtube.com/watch?v=vYVr50hjFbQ>.
+    * <https://www.youtube.com/watch?v=xh20btybjp4>.
+    * <https://www.youtube.com/watch?v=JMDycaD-YwY>.
+    * <https://www.youtube.com/watch?v=dQT6T3Zo-oA>.
+    * <https://www.youtube.com/watch?v=9sgQMHtLPNU>.
+  * <https://www.youtube.com/watch?v=lgs7d5saFFc>.
+
 ```{r}
 #-----------------------------------------------------------------------
-# Uma senhora toma chá.
+# O curioso caso da senhora que toma chá.
 
 # Quantidade de maneiras de gerar dois grupos de 4 xícaras usando 8.
 n_poss <- choose(8, 4)
 n_poss
 
+# E se fossem 12 xícaras, 6 de cada?
+choose(12, 6)
+
 # De 4 xícaras selecionadas para um grupo, X representa o número de
 # acertos.
 n_acertar <- sapply(4:0,
@@ -40,15 +66,18 @@ n_acertar <- sapply(4:0,
                     })
 n_acertar
 
-# Pr(Acerto total) = 1/70 < 5%.
-cumsum(n_acertar)/n_poss
+# Pr(Acerto total) = Pr(X = 4) = 1/70 < 5%.
+cbind(X = 4:0, "Pr(X = x)" = n_acertar/n_poss)
 
 # Comprovando por simulação.
+# Uma particular configuração das xícaras.
 v <- rep(0:1, each = 4)
+
+# Com qual frequência, ao acaso, a mesma configuração ocorre?
 mean(replicate(n = 100000,
                expr = all(sample(v) == v)))
 
-# Essa forma de fazer a conta é mais realista mas dá na mesma.
+# Essa forma de fazer é mais realista mas o resultado é o memso.
 mean(replicate(n = 100000,
                expr = all(sample(v) == sample(v))))
 ```
@@ -59,10 +88,11 @@ mean(replicate(n = 100000,
 #-----------------------------------------------------------------------
 # Exemplo com teste para a diferença de médias.
 
-# Comprimentos de crânios de cães pré-históricos.
-m <- c(120, 107, 110, 116, 114, 111, 113, 117, 114, 112)
-f <- c(110, 111, 107, 108, 110, 105, 107, 106, 111, 111)
+# Comprimentos de mandíbulas de cães pré-históricos.
+m <- c(120, 107, 110, 116, 114, 111, 113, 117, 114, 112) # machos.
+f <- c(110, 111, 107, 108, 110, 105, 107, 106, 111, 111) # fêmeas.
 
+#  Distribuição acumulada empírica.
 plot(ecdf(m), xlim = range(c(m, f)), col = "cyan")
 lines(ecdf(f), col = "magenta")
 rug(m, col = "cyan")
@@ -72,11 +102,11 @@ rug(f, col = "magenta")
 d <- mean(m) - mean(f)
 d
 
-# Todos as combinações possíveis.
+# Todos as combinações possíveis entre 20 objetos tomados 10 a 10.
 choose(n = 20, k = 10)
 
-#--------------------------------------------
-# Com todas as combinações possíveis (exaustão).
+#-----------------------------------------------------------------------
+# Solução com todas as permutações possíveis (exaustão).
 
 # Para construir todas as combinações possíveis.
 k <- combn(x = 1:20, m = 10)
@@ -85,33 +115,34 @@ dim(k)
 # Vetor com os valores dos dois grupos concatenados.
 mf <- c(m, f)
 
-# Vetor cheio de zeros.
+# Vetor de zeros.
 g <- integer(20)
 
-# Calcula a diferença para todo arranjo possível.
+# Calcula a diferença para cada uma das permutações.
 D <- apply(k,
            MARGIN = 2,
            FUN = function(i) {
-               # Alguns elementos do vetor convertidos para 1.
+               # Alguns zeros são convertidos para 1 criando 2 grupos.
                g[i] <- 1L
                # Cálculo da estatística de teste.
                -diff(tapply(mf, g, FUN = mean))
            })
 
-# Histograma da distribuição da estatística sib H_0.
+# Histograma da distribuição da estatística sob H_0.
 hist(D, col = "gray50")
 rug(D)
 abline(v = d, col = 2)
 
+# Distribuição acumulada empírica da estatística sob H_0.
 plot(ecdf(D), cex = 0)
 rug(D)
 abline(v = d, col = 2)
 
-# P-valor do teste.
+# P-valor do teste (bilateral).
 2 * sum(D >= d)/length(D)
 
-#--------------------------------------------
-# Com simulação (não necessáriamente exaustivo).
+#-----------------------------------------------------------------------
+# Com reamostragem sem reposição (não necessáriamente exaustivo).
 
 # Variáveis que indentifica os grupos.
 g <- rep(1:2, each = 10)
@@ -136,7 +167,7 @@ plot(ecdf(D), cex = 0)
 rug(D)
 abline(v = d, col = 2)
 
-# P-valor do teste.
+# P-valor do teste (bilateral).
 2 * sum(D >= d)/length(D)
 ```
 
@@ -149,12 +180,12 @@ abline(v = d, col = 2)
 # N = 5 para um par de medidas.
 x <- c(4.1, 8.3, 2.9, 10.8, 9.5)
 y <- c(3.7, 5.1, 1.0, 7.7, 8.9)
-
 cbind(x, y)
 
 plot(x, y)
 
-# Estatística de teste na amostra original.
+# Estatística de teste na amostra original: coeficiente de correlação de
+# Pearson.
 r0 <- cor(x, y, method = "pearson")
 r0
 
@@ -166,6 +197,11 @@ head(X)
 # As 120 correlações obtidas para cada arranjo.
 r <- apply(X, MARGIN = 1, FUN = cor, y = y, method = "spearman")
 
+#  Gráfico da distribuição da estatística de teste.
+plot(ecdf(r), cex = 0)
+rug(r)
+abline(v = r0, col = 2)
+
 # P-valor do teste.
 2 * sum(r >= r0)/length(r)
 ```
@@ -181,25 +217,38 @@ r <- apply(X, MARGIN = 1, FUN = cor, y = y, method = "spearman")
 #-----------------------------------------------------------------------
 # Índice de Moran para medir dependência espacial.
 
-# Coordenadas dos eventos em uma malha regular.
+# Coordenadas dos eventos em uma malha regular 8 x 8.
 x <- 1:8
 y <- 1:8
 
-# Para criar a matriz de pesos.
-ind <- expand.grid(i = 1:length(x), j = 1:length(y))
+# Construção da matriz de pesos que determina a vizinhança entre
+# observações.
+ind <- expand.grid(i = 1:length(x),
+                   j = 1:length(y))
+#  Função que determina o peso entre duas localizações na malha.
 f <- function(i, j) {
     u <- min(3, sum(abs(ind[i, ] - ind[j, ])))
-    c(0, 1, sqrt(1/2), 0)[u + 1]
+    w <- c(0, 1, sqrt(1/2), 0)[u + 1]
+    return(w)
 }
-w <- matrix(0, nrow(ind), nrow(ind))
+#  Cria os pesos, matriz (8^2) x (8^2) = 64 x 64.
+w <- matrix(0, nrow = nrow(ind), ncol = nrow(ind))
 for (i in 1:nrow(ind)) {
     for (j in 1:nrow(ind)) {
         w[i, j] <- f(i, j)
     }
 }
+#  Normaliza.
 w <- w/sum(w)
 
-image(w)
+#  Gráfico. Valores claros indicam maior peso entre observações.
+image(w, asp = 1, col = gray.colors(100))
+
+#  Lógica do índica de Moran: correlação entre valores observados e
+#  média dos vizinhos. Exemplo com valores simulados.
+xx <- rnorm(64)
+cor(cbind("Valores observados" = xx,
+          "Média dos vizinhos" = as.vector(xx %*% w)))
 
 # Índice de Moran.
 moran <- function(x, weights) {
@@ -211,7 +260,7 @@ moran <- function(x, weights) {
     as.vector(z %*% weights %*% (z * sqrt(n/(n - 1))))
 }
 
-# Teste de permutação com gráfico.
+# Teste de permutação com saída gráfica.
 ppt <- function(z, w, N = 10000, stat, ...) {
     # Índice de Moran por reamostragem.
     sim <- replicate(N,
@@ -238,6 +287,9 @@ z <- matrix(rexp(length(x) * length(y),
             length(x))
 image(log(z), main = "Com dependência")
 
+cor(cbind("Valores observados" = as.vector(z),
+          "Média dos vizinhos" = as.vector(as.vector(z) %*% w)))
+
 # Índice de Moran com dados originais.
 stat <- moran(z, w)
 stat
@@ -250,6 +302,9 @@ ppt(z, w, stat = stat, main = "I de Moran", xlab = "I")
 z <- matrix(rnorm(length(x) * length(y), 0, 1/2), length(x))
 image(z, main = "Sem dependência")
 
+cor(cbind("Valores observados" = as.vector(z),
+          "Média dos vizinhos" = as.vector(as.vector(z) %*% w)))
+
 # Índice de Moran com dados originais.
 stat <- moran(z, w)
 stat
@@ -266,9 +321,12 @@ ppt(z, w, stat = stat, main = "I de Moran", xlab = "I")
 #-----------------------------------------------------------------------
 # Aplicação de Jackknife em modelos de regressão não linear.
 
-library(latticeExtra)
 library(car)
 library(alr3)
+library(latticeExtra)
+
+# Documentação do conjunto de dados.
+# help(segreg)
 
 # Curva "palpite".
 start <- list(th0 = 75, th1 = 0.5, th2 = 50)
@@ -277,7 +335,7 @@ xyplot(C ~ Temp, data = segreg) +
                       0 * (x < th2), lty = 2),
           data = start)
 
-# Ajuste.
+# Ajuste do modelo não linear aos dados (modelo platô-linear).
 n0 <- nls(C ~ th0 + th1 * (Temp - th2) * (Temp >= th2) +
               0 * (Temp < th2),
           data = segreg,
@@ -286,7 +344,7 @@ n0 <- nls(C ~ th0 + th1 * (Temp - th2) * (Temp >= th2) +
 # Estimativas e medidas de ajuste.
 summary(n0)
 
-# Observados e preditos.
+# Valores observados curva ajustada.
 xyplot(C ~ Temp, data = segreg) +
     layer(panel.curve(th0 + th1 * (x - th2) * (x >= th2) +
                       0 * (x < th2)),
@@ -295,11 +353,10 @@ xyplot(C ~ Temp, data = segreg) +
 #-----------------------------------------------------------------------
 # Estimativas Jackknife para os parâmetros.
 
-
 theta <- coef(n0) # Estimativas com todos os dados.
 n <- nrow(segreg) # Número de observações.
 
-# Matriz vazia para armazenar os pseudo-valores.
+# Matriz vazia para armazenar os pseudo-valores durante iterações.
 thetaj <- matrix(0, nrow = n, ncol = length(theta))
 colnames(thetaj) <- names(theta)
 
@@ -314,16 +371,19 @@ for (i in 1:n) {
     thetaj[i, ] <- n * theta - (n - 1) * coef(n1)
 }
 
-# Os primeiros pseudo valores.
+# Alguns pseudo-valores.
 head(thetaj)
+tail(thetaj)
 
-# Estimativas pontuais.
+# Estimativas pontuais de Jackknife.
 jk <- colMeans(thetaj)
-cbind(MLE = theta, Jack = jk, Vício = theta - jk)
+rbind(MLE = theta,
+      Jackknife = jk,
+      Vício = theta - jk)
 
 # Erros padrões.
-cbind(MLE = summary(n0)$coefficients[, "Std. Error"],
-      Jack = apply(thetaj, MARGIN = 2, sd)/sqrt(n))
+rbind(MLE = summary(n0)$coefficients[, "Std. Error"],
+      Jackknife = apply(thetaj, MARGIN = 2, sd)/sqrt(n))
 
 # Pacote com função pronta para Jackknife para modelos não lineares.
 library(nlstools)
@@ -340,6 +400,8 @@ summary(j0)
 #-----------------------------------------------------------------------
 # Inferência para a DL 50.
 
+# Dados no pacote labestData: https://github.com/pet-estatistica/labestData.
+
 # library(labestData)
 # data(PaulaTb3.12)
 # str(PaulaTb3.12)
@@ -349,40 +411,50 @@ summary(j0)
 # dput(PaulaTb3.12)
 
 PaulaTb3.12 <-
-structure(list(vol = c(3.7, 3.5, 1.25, 0.75, 0.8, 0.7, 0.6, 1.1,
-0.9, 0.9, 0.8, 0.55, 0.6, 1.4, 0.75, 2.3, 3.2, 0.85, 1.7, 1.8,
-0.4, 0.95, 1.35, 1.5, 1.6, 0.6, 1.8, 0.95, 1.9, 1.6, 2.7, 2.35,
-1.1, 1.1, 1.2, 0.8, 0.95, 0.75, 1.3), razao = c(0.825, 1.09,
-2.5, 1.5, 3.2, 3.5, 0.75, 1.7, 0.75, 0.45, 0.57, 2.75, 3, 2.33,
-3.75, 1.64, 1.6, 1.415, 1.06, 1.8, 2, 1.36, 1.35, 1.36, 1.78,
-1.5, 1.5, 1.9, 0.95, 0.4, 0.75, 0.03, 1.83, 2.2, 2, 3.33, 1.9,
-1.9, 1.625), resp = c(1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
-1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1,
-1, 1, 0, 0, 1)), .Names = c("vol", "razao", "resp"), row.names = c(NA,
-39L), class = "data.frame")
+    structure(list(
+        vol = c(3.7, 3.5, 1.25, 0.75, 0.8, 0.7, 0.6, 1.1, 0.9, 0.9, 0.8,
+                0.55, 0.6, 1.4, 0.75, 2.3, 3.2, 0.85, 1.7, 1.8, 0.4,
+                0.95, 1.35, 1.5, 1.6, 0.6, 1.8, 0.95, 1.9, 1.6, 2.7,
+                2.35, 1.1, 1.1, 1.2, 0.8, 0.95, 0.75, 1.3),
+        razao = c(0.825, 1.09, 2.5, 1.5, 3.2, 3.5, 0.75, 1.7, 0.75,
+                  0.45, 0.57, 2.75, 3, 2.33, 3.75, 1.64, 1.6, 1.415,
+                  1.06, 1.8, 2, 1.36, 1.35, 1.36, 1.78, 1.5, 1.5, 1.9,
+                  0.95, 0.4, 0.75, 0.03, 1.83, 2.2, 2, 3.33, 1.9, 1.9,
+                  1.625),
+        resp = c(1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+                 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1,
+                 0, 0, 1)),
+        .Names = c("vol", "razao", "resp"),
+        row.names = c(NA, 39L),
+        class = "data.frame")
 
 layout(1)
-plot(resp ~ vol, data = PaulaTb3.12)
 
+#  Visualização dos dados.
+xyplot(resp ~ vol,
+       data = PaulaTb3.12,
+       groups = resp)
+
+#  Ajuste do modelo considerando resposta binária.
 m0 <- glm(resp ~ vol,
           data = PaulaTb3.12,
           family = binomial)
 summary(m0)
 
-# DL_50.
+# Estimativa da DL_50 a partir do modelo ajustado.
 dl <- -coef(m0)[1]/coef(m0)[2]
 
-# str(m0$family)$link
-
+# Curva ajustada.
 plot(resp ~ vol, data = PaulaTb3.12)
 curve(m0$family$linkinv(coef(m0)[1] + coef(m0)[2] * x),
       add = TRUE)
 abline(v = dl, h = 0.5, lty = 2)
 
+#  Número de observações e vetor de índices.
 n <- nrow(PaulaTb3.12)
 i <- 1:n
 
-# Estimativas por Jackknife.
+# Estimativas por Jackknife: pseudo-valores.
 DL <- sapply(i,
              FUN = function(i) {
                  m0 <- glm(resp ~ vol,
@@ -394,24 +466,30 @@ DL <- sapply(i,
                  n * dl - (n - 1) * DL
              })
 
+#  Estimativa pontual e erro-padrão por Jackknife.
 m <- mean(DL)
 e <- sd(DL)/sqrt(n)
 
+#  Comparando com as estimativas de Wald (usa método Delta).
 cbind(Est = rbind(MLE = dl,
-                  Jack = m),
+                  Jackknife = m),
       StdErr = rbind(MLE = car::deltaMethod(m0, g = "-(Intercept)/vol")["SE"],
                      Jack = e))
 
+# Distribuição acumulada empírica.
 plot(ecdf(DL))
 rug(DL)
+abline(v = c(m, dl), lty = c(1, 2), col = 2)
 
+#  Densidade empírica.
 plot(density(DL))
 rug(DL)
+abline(v = c(m, dl), lty = c(1, 2), col = 2)
 
 # NOTE: alguma pista sobre porque a distribuição fica bimodal?
 ```
 
-## Uma situação problemática
+## Condição problemática para uso do método Jackknife
 
 ```{r}
 #-----------------------------------------------------------------------
@@ -419,6 +497,7 @@ rug(DL)
 
 # Ordena o vetor de valores.
 x <- sort(precip)
+x
 
 # Calcula a mediana com os dados originais.
 M <- median(x)
@@ -453,6 +532,9 @@ length(x)
 library(alr3)
 str(turk0)
 
+# Documentação do conjunto de dados.
+# help(turk0)
+
 # Gráfico dos valores observados.
 plot(Gain ~ A, data = turk0)
 
@@ -481,14 +563,16 @@ cbind(coef(n0), coef(n1))
 #-----------------------------------------------------------------------
 # Criando funções que fazem reamostragem dos dados e ajustam o modelo.
 
+# Número de observações e índices.
 n <- nrow(turk0)
 i <- 1:n
 
-myboot0 <- function(formula, start) {
+#  Função que obtém estimativas bootstrap.
+myboot <- function(formula, start) {
     n0 <- nls(formula = formula,
               data = turk0[sample(i, n, replace = TRUE), ],
               start = start)
-    coef(n0)
+    return(coef(n0))
 }
 
 #-----------------------------------------------------------------------
@@ -496,18 +580,28 @@ myboot0 <- function(formula, start) {
 
 # B = 999 reamostragens.
 b0 <- replicate(999,
-                myboot0(Gain ~ Int + Ass * A/(Mei + A), start))
+                myboot(Gain ~ Int + Ass * A/(Mei + A), start))
 b1 <- replicate(999,
-                myboot0(Gain ~ Int + Ass * (1 - 2^(-A/Mei)), start))
+                myboot(Gain ~ Int + Ass * (1 - 2^(-A/Mei)), start))
 
 # Conjunto de 1000 estimativas bootstrap.
 b0 <- cbind(b0, coef(n0))
 b1 <- cbind(b1, coef(n1))
 str(b0)
 
+#  Estimativas originais.
+mle_est <- rbind(n0 = coef(n0),
+                 n0 = coef(n1))
+
+# Estimativas bootstrap.
+bot_est <- rbind(n0 = rowMeans(b0),
+                 n1 = rowMeans(b1))
+
+mle_est
+bot_est
+
 # Calcula o vício absoluto (bootstrap - original).
-rbind(n0 = rowMeans(b0) - coef(n0),
-      n1 = rowMeans(b1) - coef(n1))
+bot_est - mle_est
 
 # Variância do estimador.
 rbind(n0 = apply(b0, MARGIN = 1, var),
@@ -531,8 +625,12 @@ rbind(n0 = apply(b0, 1, FUN = eqm),
 
 bts <- cbind(rep(1:2, each = ncol(b0)),
              as.data.frame(rbind(t(b0), t(b1))))
+
+# Matriz de diagramas de dispersão das estimativas nas amostras
+# bootstrap.
 splom(bts[, -1], groups = bts[, 1])
 
+# Cada uma das curvas que foram ajustas às amostras bootstrap.
 par(mfrow = c(1, 2))
 plot(Gain ~ A, data = turk0, type = "n")
 apply(b0,
@@ -567,8 +665,12 @@ p1 <- apply(b1, MARGIN = 2,
                 b[1] + b[2] * (1 - 2^(-0.2/b[3]))
             })
 
-cbind(Est = rbind(mean(p0), mean(p1)),
-      StdErr = rbind(sd(p0), sd(p1)))
+# Estimativa e erro-padrão para o valor predito em x = 0.4.
+est <- cbind(rbind(mean(p0), mean(p1)),
+             rbind(sd(p0), sd(p1)))
+dimnames(est) <- list(c("n0", "n1"),
+                      c("Est", "StdErr"))
+est
 ```
 
 ## Usando o pacote `boot`
@@ -578,7 +680,6 @@ cbind(Est = rbind(mean(p0), mean(p1)),
 # Usando o pacote boot.
 
 library(boot)
-library(latticeExtra)
 
 # dput(as.list(coef(n1)))
 start <- list(Int = 622.958054146589,
@@ -661,8 +762,9 @@ confint(b0, type = "bca")
 #-----------------------------------------------------------------------
 # Teste para independência de processo pontual.
 
-plot(NULL, NULL, xlim = c(0, 1), ylim = c(0, 1), asp = 1)
-lines(x = c(0, 1, 1, 0, 0), y = c(0, 0, 1, 1, 0))
+# layout(1)
+# plot(x = NULL, y = NULL, xlim = c(0, 1), ylim = c(0, 1), asp = 1)
+# lines(x = c(0, 1, 1, 0, 0), y = c(0, 0, 1, 1, 0))
 # xy <- locator(n = 20, type = "p", pch = 19)
 # dput(lapply(xy, round, digits = 3))
 
@@ -835,9 +937,6 @@ system.time(m2 <- replicate(1000, rss(m = m)))
 # Distribuição da média na amostra por conjuntos ordenados imperfeito.
 system.time(m3 <- replicate(1000, rssur(m = m, rho = 0.75)))
 
-library(lattice)
-library(latticeExtra)
-
 densityplot(~m1 + m2 + m3,
             auto.key = TRUE,
             layout = c(NA, 1)) +
-- 
GitLab