Objetivo

Verificar se as populações de Botucatu e Curitiba diferem para para um conjunto de variáveis relacionado aos hábitos e histórico das pacientes. As variáveis a serem analisadas são:

  • Nugent
  • Candida
  • Ducha e a sua frequência
  • Sabonete e a sua frequência
  • História de VB
  • Número de episódios
  • História de DST
  • Número de relações sexuais por semana
  • Número de parceiros ao ano
  • Se possui parceiro recente
  • ATC/4 meses
  • Tipo
  • Uso de camisinha e sua frequencia
  • Ocorrência de sangramento na relação sexual
  • Ocorrência de dor na relação sexual
  • Ocorrência de corrimento
  • Ocorrência de odor
  • Prurido
  • pH vaginal
  • Teste de Whiff

Leitura e asseio dos dados

library(gdata)

# Lê as tabelas de dados da planilha eletrônica.
# rm(list = objects())
da <- read.xls("estatistica.xlsx",
               sheet = 1,
               header = TRUE,
               encoding = "latin1",
               stringsAsFactors = FALSE,
               check.names = TRUE)
db <- read.xls("estatistica.xlsx",
               sheet = 2,
               header = TRUE,
               encoding = "latin1",
               stringsAsFactors = FALSE,
               check.names = TRUE)

# Cria coluna com o nome das localidades.
da$loc <- "Curitiba"
db$loc <- "Botucatu"

# Obtém as colunas comuns às duas localidades.
cm <- intersect(names(da), names(db))

# Junta as duas localidades em uma tabela só.
dx <- rbind(da[, cm], db[, cm])

# Corrige os nomes.
names(dx) <- gsub("[^[:alnum:]]", "", tolower(names(dx)))

# Remove colunas vazias.
i <- sapply(dx, class)
dx[, i == "logical"] <- NULL

# Remove variáveis de sigilo.
dx$nome <- NULL
dx$matricula <- NULL

# Estrutura da tabela de dados.
# str(dx)

# names(dx)[grep("frequencia", names(dx)) - 1]
# dput(names(dx))

simnao <- c("não" = 0, "sim" = 1)
freqsem <- list(q = "Freq. semanal de consumo (dias)",
                l = c("<3" = 0, "3-6" = 1, "7" = 2))

form <-
    list("noid",
         "datacoleta",
         "nugent" = list("q" = "Nugent"),
         "candida" = list(q = "Candida",
                          l = simnao),
         "resideem" = list(q = "Reside em",
                           l = c("urbana" = "u",
                                 "rural" = "r")),
         "idade" = list(q = "Idade (anos)"),
         "peso" = list(q = "Peso (kg)"),
         "altura" = list(q = "Altura (m)"),
         "estadocivil" = list(q = "Estado civil",
                              l = c("ue/casada" = "u",
                                    "solteira" = "s")),
         "cor" = list(q = "Cor (auto-reportada)",
                      l = c("negra" = "n",
                            "branca" = "b",
                            "amarela" = "a",
                            "indigena" = "i")),
         "escolaridade" = list(q = "Escolaridade (anos de aprovação escolar)"),
         "atividaderemunerada" = list(q = "Exerce atividade remuneara",
                                      l = simnao),
         "leitequeijo" = list(q = "Consumo de leite integral/queijos",
                              l = simnao),
         "frequencia" = freqsem,
         "mamaooutros" = list(q = "Consumo de mamão/cenoura/ovo/fígado bovino",
                              l = simnao),
         "frequencia1" = freqsem,
         "fumante" = list(q = "Fumante",
                          l = simnao),
         "nrcigarrosdia" = list(q = "Número de cigarros ao dia"),
         "alcool" = list(q = "Consumo de bebida alcoólica",
                         l = simnao),
         "frequenciasem" = freqsem,
         "drogas" = list(q = "Uso de drogas",
                         l = simnao),
         "qual" = list(q = "Qual a droga"),
         "ducha" = list(q = "Realiza ducha vaginal",
                        l = simnao),
         "frequencia2" = freqsem,
         "sabonete" = list(q = "Usa sabonete intimo",
                           l = simnao),
         "frequencia3" = freqsem,
         "outroshabitos" = list(q = "Outros hábitos relacionados à higiene vaginal"),
         "dataum" = list(q = "Data da última menstruação",
                         e = "as.Date"),
         "historiavb" = list(q = "História de VB",
                             l = simnao),
         "nrepisodiostto" = list(q = "Número de epsódios de VB tratados"),
         "historiadst" = list(q = "História de DST",
                              l = simnao),
         "qual1" = list(q = "Quais DSTs"),
         "nrrssem" = list(q = "Frequência de relações sexuais (rel/semana)"),
         "parceirosano" = list(q = "Número de parceiros sexuais (último ano)",
                               l = c("0" = "0",
                                     "1" = "1",
                                     "2" = "2",
                                     ">2" = ">2")),
         "parceirorecente" = list(q = "Novo parceiro recente (últimos 2 meses)",
                                  l = simnao),
         "atc4meses" = list(q = "Uso de métodos contraceptivos (4 meses anteriores)",
                            l = simnao),
         "tipo" = list(q = "Tipo de método contraceptivo"),
         "camisinha" = list(q = "Uso de camisinha feminina ou masculina",
                            l = simnao),
         "frequencia4" = list(q = "Qual frequência de uso",
                              l = c("sempre" = 2,
                                    "às vezes" = 1)),
         "paridade" = list(q = "Paridade",
                           l = c("Nulípara" = 0,
                                 "Multipara" = 1)),
         "complanteriores" = list(q = "Complicações anteriores",
                                  l = simnao),
         "qual2" = list(q = "Quais complicações"),
         "sangrato" = list(q = "Sangramento intermenstrual (entre ciclos)",
                           l = simnao),
         "dorrs" = list(q = "Dor durante relação sexual",
                        l = simnao),
         "frequencia5" = list(q = "Dor ocorre",
                              l = c("Durante" = 0,
                                    "Após" = 1,
                                    "Ambos" = 2)),
         "corrimento" = list(q = "Corrimento",
                             l = simnao),
         "odor" = list(q = "Odor",
                       l = simnao),
         "prurido" = list(q = "Prurido",
                          l = simnao),
         "ph" = list(q = "pH",
                     l = c("<4.5", ">=4.5"),
                     b = c(0, 4.5, 14)),
         "whiff" = list(q = "Teste de Whiff",
                        l = c("Positivo" = 2,
                              "Negativo" = 0,
                              "Duvidoso" = 1)),
         "jec" = list(q = "JEC",
                      l = c(0, -1, -2, -3)),
         "vulvite" = list(q = "Vulvite",
                          l = simnao),
         "outrosachados" = NULL,
         "pcrchlamydia" = NULL,
         "pcrneisseria" = NULL,
         "loc")

# Remove variáveis que não serão usadas.
i <- sapply(form, is.null)
dx <- dx[, !i]
# names(dx)

# Converte categorias numéricas para fator.
i <- 51
rm(i)


for (i in names(dx)) {
    f <- form[[i]]
    if (!is.null(f$l)) {
        if (!is.null(f$b)) {
            dx[, i] <- factor(cut(dx[, i],
                                  breaks = f$b,
                                  labels = f$l))
        } else {
            dx[, i] <- factor(dx[, i],
                              levels = f$l,
                              labels = if (is.null(names(f$l))) {f$l}
                                       else {names(f$l)})
        }
    }
}

# Estrutura da tabela de dados.
# str(dx)

# Visão resumida da tabela de dados.
summary(dx)
##      noid            datacoleta            nugent       candida   
##  Length:228         Length:228         Min.   : 0.000   não :205  
##  Class :character   Class :character   1st Qu.: 0.000   sim : 20  
##  Mode  :character   Mode  :character   Median : 2.000   NA's:  3  
##                                        Mean   : 3.173             
##                                        3rd Qu.: 6.000             
##                                        Max.   :10.000             
##                                        NA's   :3                  
##    resideem       idade            peso            altura     
##  urbana:222   Min.   :17.00   Min.   : 43.00   Min.   :1.400  
##  rural :  4   1st Qu.:24.25   1st Qu.: 57.00   1st Qu.:1.560  
##  NA's  :  2   Median :34.00   Median : 64.00   Median :1.610  
##               Mean   :32.76   Mean   : 67.54   Mean   :1.614  
##               3rd Qu.:40.00   3rd Qu.: 74.00   3rd Qu.:1.650  
##               Max.   :51.00   Max.   :144.00   Max.   :1.780  
##               NA's   :2       NA's   :3        NA's   :3      
##     estadocivil        cor       escolaridade   
##  ue/casada:136   negra   : 77   Min.   : 0.000  
##  solteira : 90   branca  :146   1st Qu.: 7.000  
##  NA's     :  2   amarela :  2   Median :11.000  
##                  indigena:  1   Mean   : 9.509  
##                  NA's    :  2   3rd Qu.:11.000  
##                                 Max.   :20.000  
##                                 NA's   :2       
##  atividaderemunerada leitequeijo frequencia mamaooutros frequencia1
##  não : 80            não : 21    <3  : 34   não : 16    <3  :95    
##  sim :146            sim :205    3-6 : 41   sim :210    3-6 :54    
##  NA's:  2            NA's:  2    7   :130   NA's:  2    7   :61    
##                                  NA's: 23               NA's:18    
##                                                                    
##                                                                    
##                                                                    
##  fumante    nrcigarrosdia    alcool    frequenciasem  drogas   
##  não :185   Min.   : 1.00   não :162   <3  : 53      não :223  
##  sim : 41   1st Qu.: 7.75   sim : 64   3-6 :  4      sim :  3  
##  NA's:  2   Median :10.00   NA's:  2   7   :  0      NA's:  2  
##             Mean   :14.30              NA's:171                
##             3rd Qu.:20.00                                      
##             Max.   :40.00                                      
##             NA's   :188                                        
##      qual            ducha     frequencia2 sabonete   frequencia3
##  Length:228         não :188   <3  : 20    não :132   <3  : 20   
##  Class :character   sim : 38   3-6 :  7    sim : 94   3-6 : 16   
##  Mode  :character   NA's:  2   7   : 11    NA's:  2   7   : 54   
##                                NA's:190               NA's:138   
##                                                                  
##                                                                  
##                                                                  
##  outroshabitos         dataum          historiavb
##  Length:228         Length:228         não :111  
##  Class :character   Class :character   sim :115  
##  Mode  :character   Mode  :character   NA's:  2  
##                                                  
##                                                  
##                                                  
##                                                  
##  nrepisodiostto     historiadst    qual1          
##  Length:228         não :165    Length:228        
##  Class :character   sim : 61    Class :character  
##  Mode  :character   NA's:  2    Mode  :character  
##                                                   
##                                                   
##                                                   
##                                                   
##    nrrssem          parceirosano parceirorecente atc4meses 
##  Length:228         0   : 10     não :190        não :107  
##  Class :character   1   :198     sim : 36        sim :119  
##  Mode  :character   2   : 13     NA's:  2        NA's:  2  
##                     >2  :  2                               
##                     NA's:  5                               
##                                                            
##                                                            
##      tipo           camisinha    frequencia4       paridade  
##  Length:228         não :151   sempre  : 43   Nulípara : 75  
##  Class :character   sim : 75   às vezes: 29   Multipara:151  
##  Mode  :character   NA's:  2   NA's    :156   NA's     :  2  
##                                                              
##                                                              
##                                                              
##                                                              
##  complanteriores    qual2           sangrato    dorrs    
##  não :112        Length:228         não :183   não :133  
##  sim : 43        Class :character   sim : 43   sim : 93  
##  NA's: 73        Mode  :character   NA's:  2   NA's:  2  
##                                                          
##                                                          
##                                                          
##                                                          
##   frequencia5  corrimento   odor     prurido        ph     
##  Durante: 35   não :138   não :174   não :187   <4.5 : 90  
##  Após   : 36   sim : 88   sim : 52   sim : 39   >=4.5:136  
##  Ambos  : 22   NA's:  2   NA's:  2   NA's:  2   NA's :  2  
##  NA's   :135                                               
##                                                            
##                                                            
##                                                            
##       whiff      jec      vulvite        loc           
##  Positivo:99   0   :119   não :212   Length:228        
##  Negativo:94   -1  : 63   sim : 12   Class :character  
##  Duvidoso:33   -2  : 37   NA's:  4   Mode  :character  
##  NA's    : 2   -3  :  7                                
##                NA's:  2                                
##                                                        
## 
#--------------------------------------------
# Pacotes.

library(plyr)
library(reshape2)
library(knitr)

Variáveis categóricas

Para a avaliação da igualdade entre as populações de Curitiba e Botucatu com relação as variáveis categóricas, foram obtidas as tabelas de frequência absoluta. O teste \(\chi\)-quadrado foi aplicado para testar a hipótese nula de que as populações não diferem nas proporções das classes em cada variável categórica. As tabelas contém a frequência de cada classe por localidade. O p-valor do teste de \(\chi\)-quadrado foi corrigido para multiplicidade utilizando o método de Bonferroni considerando o número de variáveis categóricas sob avaliação.

#--------------------------------------------
# Variáveis categóricas.

x <- "ph"

cat_resume <- function(x) {
    dd <- ddply(.data = dx,
                .variables = c("loc", x),
                nrow,
                .drop = FALSE)
    names(dd)[2] <- "cat"
    # aggregate(V1 ~ loc, data = dd, FUN = sum, na.rm = TRUE)
    dd <- dcast(dd,
                formula = cat ~ loc,
                value.var = "V1")
    # Remove missings e linhas inteiras com zeros.
    dd <- dd[!is.na(dd$cat) & rowSums(dd[, -1]) > 0, ]
    # Corrige os p-valores usando Bonferroni.
    pval <- min(ntests * suppressWarnings(chisq.test(dd[, -1])$p.value),
                1)
    if (pval < 0.0001) pval <- "<0.0001"
    dd <- rbind(dd, data.frame(cat = "Total",
                               as.data.frame(t(colSums(dd[, -1])))))
    dd <- cbind(dd, Total = rowSums(dd[, -1]))
    dd$"$\\chi^2$ p-valor" <- c(pval, rep(NA, nrow(dd) - 1))
    return(dd)
}

i <- sapply(dx, is.factor)
ntests <- sum(i)
res <- sapply(names(dx)[i],
              simplify = FALSE,
              FUN = cat_resume)

for (i in names(res)) {
    cap <- tbn_(name = i,
                caption = paste0(form[[i]]$q, "."))
    tb <- res[[i]]
    rownames(tb) <- tb$cat
    tb$cat <- NULL
    x <- kable(x = tb,
               align = "c",
               digits = c(0, 0, 0, 5),
               caption = cap)
    cat("\n\n\n")
    cat(gsub("\\bNA\\b", "", x), sep = "\n")
}
Tabela 1: Candida.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 97 108 205 0.3811
sim 16 4 20
Total 113 112 225
Tabela 2: Reside em.
Botucatu Curitiba Total \(\chi^2\) p-valor
urbana 109 113 222 1
rural 4 0 4
Total 113 113 226
Tabela 3: Estado civil.
Botucatu Curitiba Total \(\chi^2\) p-valor
ue/casada 75 61 136 1
solteira 38 52 90
Total 113 113 226
Tabela 4: Cor (auto-reportada).
Botucatu Curitiba Total \(\chi^2\) p-valor
negra 48 29 77 0.42147
branca 62 84 146
amarela 2 0 2
indigena 1 0 1
Total 113 113 226
Tabela 5: Exerce atividade remuneara.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 52 28 80 0.04959
sim 61 85 146
Total 113 113 226
Tabela 6: Consumo de leite integral/queijos.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 16 5 21 0.79022
sim 97 108 205
Total 113 113 226
Tabela 7: Freq. semanal de consumo (dias).
Botucatu Curitiba Total \(\chi^2\) p-valor
<3 18 16 34 1
3-6 19 22 41
7 60 70 130
Total 97 108 205
Tabela 8: Consumo de mamão/cenoura/ovo/fígado bovino.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 11 5 16 1
sim 102 108 210
Total 113 113 226
Tabela 9: Freq. semanal de consumo (dias).
Botucatu Curitiba Total \(\chi^2\) p-valor
<3 57 38 95 0.00509
3-6 29 25 54
7 16 45 61
Total 102 108 210
Tabela 10: Fumante.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 85 100 185 0.56399
sim 28 13 41
Total 113 113 226
Tabela 11: Consumo de bebida alcoólica.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 91 71 162 0.18104
sim 22 42 64
Total 113 113 226
Tabela 12: Freq. semanal de consumo (dias).
Botucatu Curitiba Total \(\chi^2\) p-valor
<3 18 35 53 1
3-6 4 0 4
Total 22 35 57
Tabela 13: Uso de drogas.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 112 111 223 1
sim 1 2 3
Total 113 113 226
Tabela 14: Realiza ducha vaginal.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 96 92 188 1
sim 17 21 38
Total 113 113 226
Tabela 15: Freq. semanal de consumo (dias).
Botucatu Curitiba Total \(\chi^2\) p-valor
<3 11 9 20 1
3-6 4 3 7
7 2 9 11
Total 17 21 38
Tabela 16: Usa sabonete intimo.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 80 52 132 0.00967
sim 33 61 94
Total 113 113 226
Tabela 17: Freq. semanal de consumo (dias).
Botucatu Curitiba Total \(\chi^2\) p-valor
<3 6 14 20 1
3-6 4 12 16
7 20 34 54
Total 30 60 90
Tabela 18: História de VB.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 62 49 111 1
sim 51 64 115
Total 113 113 226
Tabela 19: História de DST.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 103 62 165 <0.0001
sim 10 51 61
Total 113 113 226
Tabela 20: Número de parceiros sexuais (último ano).
Botucatu Curitiba Total \(\chi^2\) p-valor
0 2 8 10 1
1 101 97 198
2 8 5 13
>2 0 2 2
Total 111 112 223
Tabela 21: Novo parceiro recente (últimos 2 meses).
Botucatu Curitiba Total \(\chi^2\) p-valor
não 92 98 190 1
sim 21 15 36
Total 113 113 226
Tabela 22: Uso de métodos contraceptivos (4 meses anteriores).
Botucatu Curitiba Total \(\chi^2\) p-valor
não 62 45 107 1
sim 51 68 119
Total 113 113 226
Tabela 23: Uso de camisinha feminina ou masculina.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 79 72 151 1
sim 34 41 75
Total 113 113 226
Tabela 24: Qual frequência de uso.
Botucatu Curitiba Total \(\chi^2\) p-valor
sempre 20 23 43 1
às vezes 14 15 29
Total 34 38 72
Tabela 25: Paridade.
Botucatu Curitiba Total \(\chi^2\) p-valor
Nulípara 28 47 75 0.39592
Multipara 85 66 151
Total 113 113 226
Tabela 26: Complicações anteriores.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 63 49 112 1
sim 24 19 43
Total 87 68 155
Tabela 27: Sangramento intermenstrual (entre ciclos).
Botucatu Curitiba Total \(\chi^2\) p-valor
não 98 85 183 1
sim 15 28 43
Total 113 113 226
Tabela 28: Dor durante relação sexual.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 61 72 133 1
sim 52 41 93
Total 113 113 226
Tabela 29: Dor ocorre.
Botucatu Curitiba Total \(\chi^2\) p-valor
Durante 24 11 35 0.52628
Após 13 23 36
Ambos 14 8 22
Total 51 42 93
Tabela 30: Corrimento.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 61 77 138 1
sim 52 36 88
Total 113 113 226
Tabela 31: Odor.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 81 93 174 1
sim 32 20 52
Total 113 113 226
Tabela 32: Prurido.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 91 96 187 1
sim 22 17 39
Total 113 113 226
Tabela 33: pH.
Botucatu Curitiba Total \(\chi^2\) p-valor
<4.5 27 63 90 <0.0001
>=4.5 86 50 136
Total 113 113 226
Tabela 34: Teste de Whiff.
Botucatu Curitiba Total \(\chi^2\) p-valor
Positivo 39 60 99 <0.0001
Negativo 42 52 94
Duvidoso 32 1 33
Total 113 113 226
Tabela 35: JEC.
Botucatu Curitiba Total \(\chi^2\) p-valor
0 74 45 119 0.00186
-1 16 47 63
-2 19 18 37
-3 4 3 7
Total 113 113 226
Tabela 36: Vulvite.
Botucatu Curitiba Total \(\chi^2\) p-valor
não 110 102 212 1
sim 2 10 12
Total 112 112 224

Variáveis contínuas

Para a avaliação da igualdade entre as populações de Curitiba e Botucatu com relação as variáveis numéricas, foram obtidas medidas descritivas para cada localidade. Obteve-se a média, o desvio-padrão e o número de observações. O teste \(t\) foi aplicado para testar a hipótese nula de que médias das populações não difere em cada variável numérica. Também foi aplicado o teste de Kolmogorov-Smirnov para testar a igualdade da distribuição das populações. Cada teste teve o p-valor corrigido para multiplicidade utilizando o método de Bonferroni considerando o número de variáveis numéricas sob avaliação.

#--------------------------------------------
# Variáveis contínuas.

num_resume <- function(x) {
    dx$x <- dx[, x]
    # Teste t para diferença entre médias das populações.
    pval_t <- min(ntests *
                  t.test(x ~ loc,
                         data = dx,
                         var.equal = FALSE)$p.value,
                  1)
    if (pval_t < 0.0001) pval_t <- "<0.0001"
    # Teste de Kolmogorov-Smirnov.
    s <- split(x = dx$x, f = dx$loc)
    pval_ks <- min(ntests *
                   suppressWarnings(ks.test(x = s[[1]],
                                            y = s[[2]])$p.value),
                   1)
    if (pval_ks < 0.0001) pval_ks <- "<0.0001"
    dd <- ddply(.data = dx,
                .variables = c("loc"),
                .fun = summarise,
                n = sum(!is.na(x)),
                média = mean(x, na.rm = TRUE),
                despad = sd(x, na.rm = TRUE))
    dd$"t p-valor" <- c(pval_t, NA)
    dd$"KS p-valor" <- c(pval_ks, NA)
    return(dd)
}
dx$x <- NULL

i <- sapply(dx, is.numeric)
ntests <- sum(i)
res <- sapply(names(dx)[i],
              simplify = FALSE,
              FUN = num_resume)

for (i in names(res)) {
    cap <- tbn_(name = i,
                caption = paste0(form[[i]]$q, "."))
    tb <- res[[i]]
    rownames(tb) <- tb$loc
    tb$loc <- NULL
    x <- kable(x = tb,
               align = "c",
               digits = c(0, 2, 2, 5, 5),
               caption = cap)
    cat("\n\n\n")
    cat(gsub("\\bNA\\b", "", x), sep = "\n")
}
Tabela 37: Nugent.
n média despad t p-valor KS p-valor
Botucatu 113 4.39 3.38 <0.0001 <0.0001
Curitiba 112 1.95 2.82
Tabela 38: Idade (anos).
n média despad t p-valor KS p-valor
Botucatu 113 32.24 9.36 1 1
Curitiba 113 33.28 9.19
Tabela 39: Peso (kg).
n média despad t p-valor KS p-valor
Botucatu 113 68.97 17.37 0.96833 1
Curitiba 112 66.08 13.20
Tabela 40: Altura (m).
n média despad t p-valor KS p-valor
Botucatu 113 1.60 0.07 0.01738 0.20235
Curitiba 112 1.63 0.06
Tabela 41: Escolaridade (anos de aprovação escolar).
n média despad t p-valor KS p-valor
Botucatu 113 8.04 3.37 <0.0001 <0.0001
Curitiba 113 10.98 3.64
Tabela 42: Número de cigarros ao dia.
n média despad t p-valor KS p-valor
Botucatu 28 15.57 10.44 0.77342 1
Curitiba 12 11.33 6.49

Gráficos

library(ggplot2)
library(gridExtra)

n <- names(which(sapply(dx, is.numeric)))

vnum <- lapply(n,
               FUN = function(i) {
                   ggplot(data = dx,
                          mapping = aes(x = loc,
                                        y = dx[, i])) +
                       geom_boxplot(aes(fill = loc)) +
                       scale_fill_discrete(guide = FALSE) +
                       labs(x = "Localidade",
                            y = form[[i]]$q)
               })

vnum$ncol <- 3
# length(vnum) - 1

do.call(grid.arrange, args = vnum)

n <- names(which(sapply(dx, is.factor)))

z <- 0
vcat <- lapply(n,
               FUN = function(i) {
                   j <- !is.na(dx[, i])
                   gg <- ggplot(data = dx[j, ],
                                mapping = aes(x = dx[j, i])) +
                       geom_bar(aes(fill = loc, color = I("black")),
                                position = "dodge") +
                       labs(y = "Frequência absoluta",
                            x = form[[i]]$q)
                   if (z == 0) {
                       z <<- 1
                       return(gg +
                              scale_fill_discrete(name = "Localidade") +
                              theme(legend.justification = c(1, 1),
                                    legend.position = c(1, 1)))
                   } else {
                       return(gg + scale_fill_discrete(guide = FALSE))
                   }
               })

vcat$ncol <- 2

do.call(grid.arrange, args = vcat)

Definições da sessão

sessionInfo()
## R version 3.4.1 (2017-06-30)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.2 LTS
## 
## Matrix products: default
## BLAS: /usr/lib/libblas/libblas.so.3.6.0
## LAPACK: /usr/lib/lapack/liblapack.so.3.6.0
## 
## locale:
##  [1] LC_CTYPE=pt_BR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=pt_BR.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=pt_BR.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=pt_BR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=pt_BR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  base     
## 
## other attached packages:
##  [1] gridExtra_2.2.1     ggplot2_2.2.1       reshape2_1.4.2     
##  [4] plyr_1.8.4          gdata_2.17.0        captioner_2.2.3    
##  [7] latticeExtra_0.6-28 RColorBrewer_1.1-2  lattice_0.20-35    
## [10] rmarkdown_1.5       knitr_1.16         
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.10     magrittr_1.5     munsell_0.4.3   
##  [4] colorspace_1.3-2 rlang_0.1.1      stringr_1.2.0   
##  [7] highr_0.6        tools_3.4.1      grid_3.4.1      
## [10] gtable_0.2.0     htmltools_0.3.6  gtools_3.5.0    
## [13] lazyeval_0.2.0   yaml_2.1.14      rprojroot_1.2   
## [16] digest_0.6.12    tibble_1.3.1     evaluate_0.10   
## [19] labeling_0.3     stringi_1.1.5    compiler_3.4.1  
## [22] methods_3.4.1    scales_0.4.1     backports_1.0.5