10 Análise descritiva de tabelas de contingência

10.1 Tabelas para dois ou mais fatores

Vamos utilizar aqui o conjunto de dados milsa de Bussab & Morettin discutidos na Seção 8.2 e que pode ser obtido conforme comando a seguir. Repetimos aqui o preparo inicial dos dados convertendo as variáveis categóricas em fatores do R e criando a variável idade a partir de ano e mes.

> milsa <- read.table("http://www.leg.ufpr.br/Rembrapa/dados/milsa.dat", head=T) 
> milsa <- transform(milsa, civil=factor(civil, label=c("solteiro", "casado"), levels=1:2), 
+                    instrucao = factor(instrucao, 
+                            label=c("1oGrau", "2oGrau", "Superior"), lev=1:3, ord=T), 
+                    regiao = factor(regiao, 
+                            label=c("capital", "interior", "outro"), lev=c(2,1,3))) 
> milsa <- transform(milsa, idade = ano + mes/12) 
> names(milsa)

Tabelas de contingência podem ser obtidas com as frequências de ocorrência nos cruzamentos de variáveis. A seguir mostramos algumas opções da visualização dos resultados usando a função table() e a função ftable(). As funções retornam as tabelas de contingência em um objeto que pode ser uma matrix, no caso do cruzamento de duas variáveis, ou de forma mais geral, na forma de um array, onde o número de dimensões é igual ao número de variáveis. A classe do objeto resultante vai depender da função utilizada. Nesse caso, para o cruzamento de apenas duas variáveis, os resultados são exibidos de forma semelhante. No exemplo consideram-se as variáveis civil e instrucao que estão situadas nas colunas 2 e 3 do data.frame.

> t1 <- table(milsa[c(2,3)]) 
> t1

          instrucao 
civil      1oGrau 2oGrau Superior 
  solteiro      7      6        3 
  casado        5     12        3

> t1f <- ftable(milsa[c(2,3)]) 
> t1f

         instrucao 1oGrau 2oGrau Superior 
civil 
solteiro                7      6        3 
casado                  5     12        3

> sapply(list(t1, t1f), class)

[1] "table"  "ftable"

> sapply(list(t1, t1f), is.matrix)

[1] TRUE TRUE

> sapply(list(t1, t1f), is.array)

[1] TRUE TRUE

Ambas funções possuem o argumento dnn que pode ser usado para sobrescrever os nomes das dimensões do objeto resultante.

> dimnames(t1)

$civil 
[1] "solteiro" "casado" 
 
$instrucao 
[1] "1oGrau"   "2oGrau"   "Superior"

> t1 <- table(milsa[c(2,3)], dnn=c("Estado Civil","Nível de Instrução")) 
> dimnames(t1)

$`Estado Civil` 
[1] "solteiro" "casado" 
 
$`Nível de Instrução` 
[1] "1oGrau"   "2oGrau"   "Superior"

> t1f <- ftable(milsa[c(2,3)], dnn=c("Estado Civil","Nível de Instrução"))

As diferenças na forma de exibir os resultados são mais claras considerando-se o cruzamento entre três ou mais variáveis. Enquanto table() vai exibir um array da forma usual, mostrando as várias camadas separadamente, ftable() irá arranjar a tabela de forma plana, em uma visualização mais adequada para a leitura dos dados. Vamos considerar o cruzamento das variáveis civil, instrucao e regiao situadas nas colunas 2, 3 e 8 do data.frame.

> t2 <- with(milsa,table(civil,instrucao,regiao)) 
> t2

, , regiao = capital 
 
          instrucao 
civil      1oGrau 2oGrau Superior 
  solteiro      2      1        1 
  casado        2      4        1 
 
, , regiao = interior 
 
          instrucao 
civil      1oGrau 2oGrau Superior 
  solteiro      2      1        1 
  casado        1      6        1 
 
, , regiao = outro 
 
          instrucao 
civil      1oGrau 2oGrau Superior 
  solteiro      3      4        1 
  casado        2      2        1

> t2f <- with(milsa,ftable(civil,instrucao,regiao)) 
> t2f

                   regiao capital interior outro 
civil    instrucao 
solteiro 1oGrau                 2        2     3 
         2oGrau                 1        1     4 
         Superior               1        1     1 
casado   1oGrau                 2        1     2 
         2oGrau                 4        6     2 
         Superior               1        1     1

O objeto retornado por table() não é uma matriz, mas sim um array de três dimensões, por serem três variáveis. A dimensão do array é de \(2\times 3\times 3\) por haver 2 estados civis, 3 níveis de instrução e 3 regiões. Já o objeto retornado por ftable() ainda é uma matriz, neste caso de dimensão \(6\times 3\) onde \(6=2\times 3\) indicando o produto do número de níveis das duas primeiras variáveis.

> sapply(list(t2,t2f), is.matrix)

[1] FALSE  TRUE

> sapply(list(t2,t2f), is.array)

[1] TRUE TRUE

> sapply(list(t2,t2f), dim)

[[1]] 
[1] 2 3 3 
 
[[2]] 
[1] 6 3

Com ftable() é possível ainda criar outras visualizações da tabela. Os argumentos row.vars e col.vars podem ser usados para indicar quais variáveis serão colocadas nas linhas e colunas, e em que ordem. No exemplo a seguir colocamos o estado civil e região de procedência (variáveis 1 e 3) nas colunas da tabela e também modificamos o nome das dimensões da tabela com o argumento dnn. O objeto resultante é uma matriz de dimensão \(6\times 3\).

> with(milsa, ftable(civil,instrucao,regiao, 
+                    dnn=c("Estado Civil","Nível de Instrução", "Procedência"), 
+                    col.vars=c(1,3)))

                   Estado Civil solteiro                 casado 
                   Procedência   capital interior outro capital interior outro 
Nível de Instrução 
1oGrau                                 2        2     3       2        1     2 
2oGrau                                 1        1     4       4        6     2 
Superior                               1        1     1       1        1     1

10.2 Extensões: frequências relativas e gráficos

As funções table() e ftable() retornam objetos das classes table e ftable, respectivamente. A partir de tais objetos, outras funções podem ser utilizadas tais como prop.table() para obtenção de frequências relativas ou barplot() para gráficos de barras. A distinção entre as classes não é importante no caso de cruzamento entre apenas duas variáveis. Entretanto, para três ou mais variáveis os resultados são bem diferentes, devido ao fato já mencionado de que table() retorna um array de dimensão igual ao número de variáveis, enquanto ftable() retorna sempre uma matriz.

Considerando os exemplos da Seção anterior, vejamos primeiro os resultados de frequências relativas para duas variáveis, que não diferem entre as classes. Da mesma forma, no caso de duas variáveis, as margens das tabelas obtidas de uma ou outra forma são as mesmas. O valor numérico retornado por margin.table() é idêntico para t1 e t1f, ainda que, em versões recentes do R, imprimir o resultado de margin.table() aplicado a um ftable totalmente colapsado (reduzido a uma única dimensão) provoque um erro interno em print.ftable(); por isso abaixo mostramos a impressão apenas para o objeto t1.

> prop.table(t1)

            Nível de Instrução 
Estado Civil     1oGrau     2oGrau   Superior 
    solteiro 0.19444444 0.16666667 0.08333333 
    casado   0.13888889 0.33333333 0.08333333

> prop.table(t1f)

         instrucao     1oGrau     2oGrau   Superior 
civil 
solteiro           0.19444444 0.16666667 0.08333333 
casado             0.13888889 0.33333333 0.08333333

> prop.table(t1, margin=1)

            Nível de Instrução 
Estado Civil 1oGrau 2oGrau Superior 
    solteiro 0.4375 0.3750   0.1875 
    casado   0.2500 0.6000   0.1500

> prop.table(t1f, margin=1)

         instrucao 1oGrau 2oGrau Superior 
civil 
solteiro           0.4375 0.3750   0.1875 
casado             0.2500 0.6000   0.1500

> margin.table(t1, mar=1)

Estado Civil 
solteiro   casado 
      16       20

> ## margin.table(t1f, mar=1) produz o mesmo resultado numérico de 
> ## margin.table(t1, mar=1), mas sua impressão falha em versões 
> ## recentes do R devido a um problema em print.ftable() ao lidar 
> ## com um ftable de uma única dimensão. 
> margin.table(t1, mar=2)

Nível de Instrução 
  1oGrau   2oGrau Superior 
      12       18        6

> ## margin.table(t1f, mar=2) -- mesma limitação de impressão acima.

Da mesma forma os gráficos obtidos são os mesmos. A Figura 14 mostra dois tipos de gráficos. Os gráficos na parte superior mostram retângulos cujas áreas são proporcionais às frequências e abaixo um dentre os possíveis gráficos de barras.

> plot(t1, main="") 
> plot(t1f, main="") 
> barplot(t1, beside=T, legend=T) 
> barplot(t1f, beside=T, legend=T)

PIC

Figura 14: Representações gráficas de tabelas de contingência de duas variáveis obtidas pelas funções table() e ftable().

Já para três ou mais variáveis os resultados são bem diferentes, em particular para as frequências marginais, uma vez que ftable() vai sempre retornar uma matriz e portanto só possuirá margens 1 e 2.

> prop.table(t2)

, , regiao = capital 
 
          instrucao 
civil          1oGrau     2oGrau   Superior 
  solteiro 0.05555556 0.02777778 0.02777778 
  casado   0.05555556 0.11111111 0.02777778 
 
, , regiao = interior 
 
          instrucao 
civil          1oGrau     2oGrau   Superior 
  solteiro 0.05555556 0.02777778 0.02777778 
  casado   0.02777778 0.16666667 0.02777778 
 
, , regiao = outro 
 
          instrucao 
civil          1oGrau     2oGrau   Superior 
  solteiro 0.08333333 0.11111111 0.02777778 
  casado   0.05555556 0.05555556 0.02777778

> prop.table(t2f)

                   regiao    capital   interior      outro 
civil    instrucao 
solteiro 1oGrau           0.05555556 0.05555556 0.08333333 
         2oGrau           0.02777778 0.02777778 0.11111111 
         Superior         0.02777778 0.02777778 0.02777778 
casado   1oGrau           0.05555556 0.02777778 0.05555556 
         2oGrau           0.11111111 0.16666667 0.05555556 
         Superior         0.02777778 0.02777778 0.02777778

> prop.table(t2, margin=1)

, , regiao = capital 
 
          instrucao 
civil      1oGrau 2oGrau Superior 
  solteiro 0.1250 0.0625   0.0625 
  casado   0.1000 0.2000   0.0500 
 
, , regiao = interior 
 
          instrucao 
civil      1oGrau 2oGrau Superior 
  solteiro 0.1250 0.0625   0.0625 
  casado   0.0500 0.3000   0.0500 
 
, , regiao = outro 
 
          instrucao 
civil      1oGrau 2oGrau Superior 
  solteiro 0.1875 0.2500   0.0625 
  casado   0.1000 0.1000   0.0500

> prop.table(t2f, margin=1)

                   regiao   capital  interior     outro 
civil    instrucao 
solteiro 1oGrau           0.2857143 0.2857143 0.4285714 
         2oGrau           0.1666667 0.1666667 0.6666667 
         Superior         0.3333333 0.3333333 0.3333333 
casado   1oGrau           0.4000000 0.2000000 0.4000000 
         2oGrau           0.3333333 0.5000000 0.1666667 
         Superior         0.3333333 0.3333333 0.3333333

> prop.table(t2, margin=3)

, , regiao = capital 
 
          instrucao 
civil          1oGrau     2oGrau   Superior 
  solteiro 0.18181818 0.09090909 0.09090909 
  casado   0.18181818 0.36363636 0.09090909 
 
, , regiao = interior 
 
          instrucao 
civil          1oGrau     2oGrau   Superior 
  solteiro 0.16666667 0.08333333 0.08333333 
  casado   0.08333333 0.50000000 0.08333333 
 
, , regiao = outro 
 
          instrucao 
civil          1oGrau     2oGrau   Superior 
  solteiro 0.23076923 0.30769231 0.07692308 
  casado   0.15384615 0.15384615 0.07692308

É possível obter totais marginais com margin.table() a partir de um objeto resultante de table() mas não para um objeto resultante de ftable()!

> margin.table(t2, mar=1)

civil 
solteiro   casado 
      16       20

> margin.table(t2, mar=2)

instrucao 
  1oGrau   2oGrau Superior 
      12       18        6

> margin.table(t2, mar=3)

regiao 
 capital interior    outro 
      11       12       13

Para gráficos nem todos os resultados são mais possíveis, plot() vai funcionar para a classe table() mas o resultado é inapropriado para ftable(). Já barplot() irá funcionar apenas para ftable(), mas o resultado pode não ser satisfatório pois as barras irão mostrar as combinações de duas variáveis.

> plot(t2, main="") 
> barplot(t2f, beside=T)

PIC

Figura 15: Representações gráficas de tabelas de contingência de três variáveis obtidas pelas funções table() (esquerda) e ftable() (direita).