Criando um gráfico com bandeiras dos países.

Esses tempos, um colega me pediu para fazer alguns gráficos tipo os que tem no google analytics, mais especificamente nesse estilo aqui.

É de uma versão mais antiga dessa figura, mas a ideia é essa, basicamente um gráfico de barras na vertical. A única parte difícil, foi as bandeiras, primeiro foi achar essas bandeiras, depois inserir na figura.

Para achar as figuras, a primeira coisa foi procurar algum pacote que tivesse isso pronto, achei que encontraria, mas não achei nenhum, então ao procurar pelas bandeiras, uma fonte seria baixar diretamente do wikipedia, que tem bandeiras para todos os paises, mas eu achei esse conjunto aqui, que inclusive está em um repositorio do github que podemos clonar, o que facilita bastante o trabalho, ali temos as bandeiras em formato png em vários tamanhos, eu preferi usar o de maior resolução.

então clonado o repositório com as bandeiras, eu fiz a figura com o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
library(png)
paises<-list.files("64")
 
##Figura country.png
 
country<-c("Brazil","United States","Portugal","Mozambique","Mexico","Germany","Peru","Australia","Cape Verde","Angola")
country_br<-c("Brasil","Estados Unidos","Portugal","Mozambique","México","Alemanha","Perú","Austrália","Cabo Verde","Angola")
sessions<-c(2113,259,85,63,54,49,38,37,36,36)
sessions_percentage<-c(60.39,7.4,2.43,1.8,1.54,1.4,1.09,1.06,1.03,1.03)
 
ampliacao <- 2
jpeg("country.jpg",width = ampliacao*480,height = ampliacao*480,pointsize = ampliacao*12)
escala<-barplot(rev(sessions_percentage),horiz=T,xlim=c(-150,100),xaxt="n",col="#76A7FA")
text(rep(0,10),escala,rev(sessions),pos=2)
text(rev(sessions_percentage)+14,escala,paste(rev(format(round(sessions_percentage, 2), nsmall = 2)),"%",sep=""))
text(rep(-130,10),escala,10:1,pos=2)
text(rep(-120,10),escala,rev(country_br),pos=4)
mtext(c("País","Sessões","% Sessões"),3,0,at=c(-125,-15,35))
 
list.files()
 
for(i in 1:10){
    country[i]
    posicao<-agrep(country[i],paises)
    paises[posicao]
    bandeira<-readPNG(paste("64/",paises[posicao],sep=""))
    rasterImage(bandeira,-133,rev(escala)[i]-0.5,-117,rev(escala)[i]+0.5)
}
dev.off()

Que gera a seguinte figura.

Bem legal eu achei, agora vou fazer alguns comentários do meu código.

Primeiro:

1
2
country<-c("Brazil","United States","Portugal","Mozambique","Mexico","Germany","Peru","Australia","Cape Verde","Angola")
country_br<-c("Brasil","Estados Unidos","Portugal","Mozambique","México","Alemanha","Perú","Austrália","Cabo Verde","Angola")

Bem como são poucos dados, eu digitei o nomes do países em inglês e em português, isso porque o nome em inglês eu uso para achar o nome do arquivo da bandeira, que é o nome do pais, e em português para usar na figura em si.

Depois disso para facilitar a mudança do tamanho, eu costumo guardar uma variável para o tamanho, que multiplica a largura, a altura e o tamanho do ponto, assim só altero ela para mudar o tamanho da figura, a sua resolução.

1
2
3
4
5
6
ampliacao <- 2
jpeg("country.jpg",width = ampliacao*480,height = ampliacao*480,pointsize = ampliacao*12)
 
##Figura
 
dev.off()

A figura em si é um barplot na vertical, a única coisa é que mudo bastante as margens, o tamanho do eixos de forma a caber as outras informações e bandeiras, que são colocadas com a função text para dentro da figura e mtext para a parte de fora. Depois disso, talvez essa parte ainda tenha algo de interesse.

1
2
3
4
5
6
7
for(i in 1:10){
    country[i]
    posicao<-agrep(country[i],paises)
    paises[posicao]
    bandeira<-readPNG(paste("64/",paises[posicao],sep=""))
    rasterImage(bandeira,-133,rev(escala)[i]-0.5,-117,rev(escala)[i]+0.5)
}

Então eu pego o nome do pais em inglês, e uso agrep na lista de nomes de arquivos, agrep, porque é um grep, ou seja acha a palavra na lista, mas permite alguns erros de caracteres, que da para regular com argumentos, mas então com o agrep a gente vai achar o nome do arquivo, com ele a gente le a figura png com o readPNG, que le o raster da figura, então com rasterImage a gente adiciona ela a figura, aqui a gente tem que colocar os quatro pontos da imagem para adicionar ela, veja se da até para colocar a imagem espelhada, feito isso ta pronto. Para economizar, eu fiz um loop para todas as bandeiras.

Bem é isso ai, o script vai estar la no repositório recologia, e se eu escrevi alguma bobeira, algo errado, deixe um comentário corrigindo ou mande um e-mail. Um post bem simples, mas é o tipo de código que é legal guardar, pois pode ser útil copiar e colar um dia.

Gráficos circulares usando ggplot2

A gente começou a olhar o sistema de gráficos ggplot2 aqui.

Não tem como aprender nada novo sem começar a usar, então vamos tentar ver como fazer alguns gráficos simples, e um jeito legal de transformá-los em gráficos circulares. Porque se a gente fizer gráficos o suficiente, uma hora a gente fica bom de ggplot2, e como eu disse no outro post, ele tem lá suas vantagens, apesar de que qualquer coisa que da para fazer com ggplot, da para fazer com o sistema de gráficos default do R.

Mas primeiro vamos gerar um conjunto de dados bem simples:

1
dados<-data.frame(preditor=1:20,resposta=runif(20,5,10),grupo=rep(1:4,each=5),linha=runif(20,8,12))

Então temos uma coluna com uma sequencia de um a vinte, uma coluna com números aleatórios, um coluna agrupando eles e outra coluna de números aleatórios.

> head(dados) preditor resposta grupo linha 1 1 8.501650 1 8.049639 2 2 7.122299 1 8.521307 3 3 8.113232 1 9.414598 4 4 5.568166 1 8.886906 5 5 8.067636 1 11.594324 6 6 6.692768 2 8.299302

Primeiro, vamos fazer uma figura bem simples, um gráfico de barras.

1
ggplot(data=dados, aes(x=preditor, y=resposta)) + geom_bar(stat="identity")

O comando acima diz o seguinte, não função ggplot, a gente diz onde estão os dados, e o aesthetic, ou quem é quem. Mas até ai não há representação nenhuma, ou seja, precisamos de uma forma para representar os dados, e para isso vamos usar o geom_bar, que são barras, então barras representam os dados, e vamos usar a função identidade, ou seja, não vamos alterar em nada a apresentação, isso vai nos render a seguinte figura.

01

Bem simples até de usar não, parecia mais complicado no post anterior. Então, mas o aesthetic não se limita a coordenadas, podemos definir o preenchimento das barras. Dependendo do tipo de forma que presentara os dados, teremos os aesthetics de interesse, formato de linha, formato de ponto, essas coisas, mas vamos continuar nas barras aqui.

1
ggplot(data=dados, aes(x=preditor, y=resposta,fill=grupo)) + geom_bar(stat="identity")

Veja que agora somente adicionamos o fill ao aesthetic e definimos ele como o grupo.

02

O que está dentro do aesthetic do ggplot, é o que será usado de forma geral, veja que dentro desse geom que estamos usando, podemos definir característica da sua representação também, por exemplo um contorno preto.

1
ggplot(data=dados, aes(x=preditor, y=resposta,fill=grupo)) + geom_bar(colour="black",stat="identity") + guides(fill=FALSE)

Além disso, alguma coisas, como a legenda, vem por padrão, mas podemos retirar ela, se desejarmos, que é o que fazemos ao dar o guides como false.

03

Legal, agora vamos ver como fazer um gráfico de linhas.

1
ggplot(data=dados, aes(x=preditor, y=linha)) + geom_line() + guides(fill=FALSE)

Linhas são apenas outra forma de representação dos dados, so trocamos o geom, a sintaxe do aesthetic anterior continua a mesma coisa.

04

Mas é legal, que se queremos usar linhas e pontos, por exemplo, o que a gente quer são duas representações geométricas dos mesmos valores, então basta adicionar os dois geom.

1
ggplot(data=dados, aes(x=preditor, y=linha)) + geom_line() + geom_point() + guides(fill=FALSE)

E temos a seguinte figura

05

Agora e se quisermos adicionar dados diferentes de acordo com o geom, por exemplo um gráfico com barras e linhas?
Como falamos até agora, isso implica em mais de uma aesthetic, mas podemos definir mais de um aesthetic, dentro de cada geom, podemos definir seu próprio aesthetic, se não definimos, ele usa o padrão definido dentro da função ggplot.

1
2
ggplot(data=dados, aes(x=preditor, y=resposta,fill=grupo)) + geom_bar(colour="black",stat="identity") + guides(fill=FALSE) +
    geom_line(data=dados, aes(x=preditor, y=linha)) + geom_point(data=dados, aes(x=preditor, y=linha))

E temos a seguinte figura.

06

Uma coisa legal, é que como tudo é interpretado de uma so vez, o ggplot vai tentar colocar tudo que você quer na mesma figura, por exemplo, ele tenta acertar a escala, para caber todo mundo, diferente do sistema gráfico padrão do R, que aqui exigiria dois passos, e nos teríamos que nos preocupar com a escala da figura também, que teria seu limites definido baseado em um dos aesthetics.

Mas como tornar essa figura circular? Aqui está a parte legal, basta trocar o sistema de coordenadas, nesse caso, por padrão, estamos usando o plano cartesiano, basta mudar para o plano circular e ta pronto, uma figura circular.

1
2
ggplot(data=dados, aes(x=preditor, y=resposta,fill=grupo)) + geom_bar(colour="black",stat="identity") + guides(fill=FALSE) +
    geom_line(data=dados, aes(x=preditor, y=linha)) + geom_point(data=dados, aes(x=preditor, y=linha))+coord_polar()

Veja que o que mudou, foi a adição do coord_polar, e ficamos com o seguinte.

07

Agora aqui é preciso atenção, veja que as barras, e os pontos, bem os pontos são o centro das barras, então quando fazemos uma figura de barras, os pontos não vão fechar, veja que so mudamos o plano, o que era a extensão do eixo x virou ângulos, de 0 a 360, e o eixo y virou raio.

Se tiramos as barras

1
ggplot(data=dados, aes(x=preditor, y=linha)) + geom_line() + geom_point() + guides(fill=FALSE) + coord_polar()

Temos que os pontos começam e terminam no “mesmo lugar”.

08.

Mas temos que ter atenção ainda, porque não da para ver direito o eixo y, no sentido de onde começa e termina em valores, mas ele nao esta começando do zero, temos que delimitar o inicio e fim dele.

1
ggplot(data=dados, aes(x=preditor, y=linha)) + geom_line() + geom_point() + guides(fill=FALSE) + coord_polar() + ylim(0,12)

Agora o ponto central é zero.

09

Bem é isso ai, esses são alguns teste para aprender alguma coisa de ggplot2, o script vai estar la no repositório recologia, e se eu escrevi alguma bobeira, algo errado, deixe um comentário corrigindo ou mande um e-mail.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
library("ggplot2")
 
dados<-data.frame(preditor=1:20,resposta=runif(20,5,10),grupo=rep(1:4,each=5),linha=runif(20,8,12))
head(dados)
 
## Gráfico de barras
ggplot(data=dados, aes(x=preditor, y=resposta)) + geom_bar(stat="identity")
ggsave("01.jpg")
 
## Separando por grupos
ggplot(data=dados, aes(x=preditor, y=resposta,fill=grupo)) + geom_bar(stat="identity")
##ggplot(data=dados, aes(x=preditor, y=resposta)) + geom_bar(aes(fill=grupo),stat="identity")
ggsave("02.jpg")
 
## Adicionando um contorno preto, e retirando a legenda
ggplot(data=dados, aes(x=preditor, y=resposta,fill=grupo)) + geom_bar(colour="black",stat="identity") + guides(fill=FALSE)
ggsave("03.jpg")
 
##Gráfico de linhas
ggplot(data=dados, aes(x=preditor, y=linha)) + geom_line() + guides(fill=FALSE)
ggsave("04.jpg")
ggplot(data=dados, aes(x=preditor, y=linha)) + geom_line() + geom_point() + guides(fill=FALSE)
ggsave("05.jpg")
 
##Combinando os dois
ggplot(data=dados, aes(x=preditor, y=resposta,fill=grupo)) + geom_bar(colour="black",stat="identity") + guides(fill=FALSE) +
    geom_line(data=dados, aes(x=preditor, y=linha)) + geom_point(data=dados, aes(x=preditor, y=linha))
ggsave("06.jpg")
 
 
##Transformando em uma figura circular
ggplot(data=dados, aes(x=preditor, y=resposta,fill=grupo)) + geom_bar(colour="black",stat="identity") + guides(fill=FALSE) +
    geom_line(data=dados, aes(x=preditor, y=linha)) + geom_point(data=dados, aes(x=preditor, y=linha))+coord_polar()
ggsave("07.jpg")
 
ggplot(data=dados, aes(x=preditor, y=linha)) + geom_line() + geom_point() + guides(fill=FALSE) + coord_polar()
ggsave("08.jpg")
ggplot(data=dados, aes(x=preditor, y=linha)) + geom_line() + geom_point() + guides(fill=FALSE) + coord_polar() + ylim(0,12)
ggsave("09.jpg")

O que é ggplot2?

figura01

Como o mundo é um lugar pequeno, o primeiro nome a ser citado para começar a falar algo de ggplot é o do Leland Wilkinson. Esse é o cara que criou o pacote estatístico chamado systat, que foi um dos primeiros que eu comecei usar para análises estatísticas, porque todo mundo usava e foi o primeiro que me mostraram.

Esse cara, o Wilkinson criou algo que ele chamou de gramática dos gráficos para descrever características que compõem todos os gráficos estatísticos. Ele deu a resposta para a pergunta, o que é um gráfico estatístico?

A gramática de gráficos de camadas é baseada na gramática de Wilkinson, veja que o gg do ggplot vem de “grammar of graphics”.

De forma resumida, a gramática diz para a gente que um gráfico estatístico é um mapeamento de dados para atributos estéticos (o “aesthetic” que a gente chama na função e define cor, forma, tamanho) e de objetos geométricos (pontos, linhas, barras). O gráfico também pode conter transformações estatísticas dos dados e é desenhado num sistema de coordenadas específico. Podemos ainda separar o gráfico em partes (faceting) para gerar o mesmo gráfico para diferentes subconjuntos dos dados (as figuras que fazemos usando o lattice). A combinação de todas essas coisas que fazem um gráfico.

Os dados que queremos visualizar e o mapeamento estatístico descreve como as variáveis nos dados são mapeados em atributos estáticos que a gente pode perceber. Objetos geométricos, os geoms, representam o que nos podemos ver nos gráficos, pontos, linhas, polígonos, etc. Transformações estatísticas, stats, sumarizam os dados de muitas formas úteis. Por exemplo, armazenando e contando observações para criar um histograma, ou sumarizando a relação linear de uma figura.

As escalas mapeiam valores do espaço dos dados para o espaço da estética definida, podendo ser cor, tamanho ou forma. Escalas são as coisas que formam legendas e eixos, que possibilita o mapeamento inverso para tornar possível ler os dados originais de um gráfico.

Um sistema de coordenadas, coord, descreve como as coordenadas dos dados são mapeados para um plano do gráfico. Ele também prove eixos e linhas de grid para tornar possível ler o gráfico. Nos normalmente usando o sistema cartesiano, mas muitos outros são possíveis, incluindo o sistema polar de coordenadas e projeções de mapas.

A partição do gráfico, ou faceting descreve como quebrar os dados em subgrupos e como apresentar esses grupos como pequenos múltiplos do todo. Isso também é conhecido como condicionando os dados ou latticing/trellising.

figura02

Sistemas gráficos no R

O sistema básico de gráficos do R foi escrito pelo Ross Ihaka baseado na experiência que tinha na linguagem S e olhando no livro do Chambers, Graphical methods for Data Analysis.
O sistema de gráficos básico é no modelo caneta e papel: você só pode desenha em cima do gráfico (existem funções com text para texto dentro da área de coordenadas, e mtext para a are no entorno), você não pode modificar ou deletar um componente que já desenhou. Não existe uma representação gráfica além daquela que aparece na tela. O sistema básico de gráficos inclui ferramentas para desenhar tanto gráficos primitivos como completos. As funções do sistema básico são geralmente rápidas, mas tem um escopo limitado.

O desenvolvimento de gráficos em grid é um sistema muito mais rico que começou em 2000. O grid foi desenvolvido por Paul Murrell durante o desenvolvimento da sua tese de doutorado. Objetos de grid (grid grobs) podem ser representados independentemente do gráfico e modificados depois. A partir desse sistema surgiu o pacote lattice, desenvolvido por Deepayan Sarkar, que usa o gráficos em grid para implementar o sistema de gráficos trellis de Cleveland e é visto como uma considerável melhora sobre os sistema básico de gráficos. Da para produzir facilmente gráficos condicionais e algumas modificações primitivas dentro dos sub-gráficos.

O ggplot2 começou em 2005, como uma tentativa de pegar as coisas boas do pacote lattice e melhorar elas com um modelo forte para dar suporte a produção de qualquer tipo de gráfico estatístico, baseados nos princípios da gramática de gráficos do Wilkinson.

figura04

Componentes:

Então, os gráficos são formados por dados e seu mapeamento estético (aesthetic), formas geométricas (geoms), transformações estatísticas (stats), scales e faceting. Além de um sistema de coordenadas. Essas coisas formam uma camada na gramática dos gráficos.

Um gráfico pode ter múltiplas camadas. Ou seja, um scatterplot com uma linha de tendência tem duas camadas, uma que é a os pontos e outra que é a linha de tendência, que são dados transformados por uma estatística, um stat.

Layers (Camadas)

Layers ou camadas são responsáveis por criar os objetos que nos vemos no gráfico, normalmente sendo composto por 4 partes.

Dados e seu mapeamento estético
Uma transformação estatística (se você não faz nada, esta usando a função identidade, pense nisso)
Uma forma geométrica
Um ajuste de posicionamento.

Scales (escalas)

A escala controla o mapeamento dos dados, os atributos estéticos, e nos precisamos de uma escala para cada aesthetic usado no gráfico. Cada escala opera sobre todos os dados do gráfico, garantindo um mapeamento consistente dos dados.

Uma escala é uma função, e sua função inversa junto com um conjunto de parâmetros dessa. Por exemplo, as cores de uma escala de gradiente mapeia um segmento da reta real para um caminho sobre o espaço de cores. Os parâmetros da função definem se o caminho é linear ou curvo, qual espaço de cores usar (RGB) e as cores do inicio e do fim. A função inversa é usada para desenhar um guia para que possamos ler o gráfico. Entenda que guias aqui são os eixos ou legendas. Muitos mapeamentos tem uma função inversa única, mas nem sempre. Uma função inversa única (uma função que mapeia valores um pra um) permite recuperar os valores originais dos dados, mas isso pode não ser completamente desejável se queremos focar a atenção a um único aspecto.

Coordinate system (Sistemas de coordenadas)

Um sistema de coordenadas, mapeia a posição dos objetos no plano de coordenadas. Posição é comumente especificada por duas coordenadas (x,y), mas podemos ter três ou mais. O sistema cartesiano é o mais comum para duas dimensões, mas temos o sistema polar, para gráficos circulares por exemplo e vários outro tipos de projeções de mapeamento usado menos frequentemente.

O sistema de coordenadas afeta todas as posições de variáveis simultaneamente e difere das escalas (scales) de forma que eles também alteram a aparência de objetos geométricos.
Por exemplo, no sistema polar de coordenadas, os gráficos de barras parecem segmentos de um circulo.

Adicionalmente, a escala é aplicada antes da transformação estatística, enquanto o sistema de coordenadas ocorre depois.

O sistema de coordenadas controla como os eixos e linhas de grid são desenhados

Faceting

Outra coisa é extremamente útil nesse framework todo é o faceting, o condicionamento dos dados.
É ele que torna fácil criar gráficos múltiplos, onde cada um mostra um sub-conjunto diferente de um data-set. Essa é uma ferramente poderosa para investigar se um padrão se mantêm sobre várias condições. A descrição do faceting específica qual variável deve ser usada para dividir os dados e como, se a posição na escada deve ser livre ou condicionada.

Bem é isso ai, pra quem não tinha ideia do que se tratava o ggplot2, agora a gente tem uma noção, e se eu escrevi alguma bobeira, algo errado, deixe um comentário corrigindo ou mande um e-mail.

Referência:
Hadley Wickham 2010 ggplot2: Elegant Graphics for Data Analysis – Springer 213pp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
library(ggplot2)
 
preditor<-runif(100,1,5)
resposta<-rnorm(100,2+2*preditor)
dados<-data.frame(preditor,resposta)
 
p <- ggplot(dados,aes(preditor,resposta))
p <- p + layer(geom = "point")
p
ggsave("figura01.jpg")
 
p <- ggplot(dados,aes(x=preditor))
p <- p + layer(geom = "bar",geom_params = list(fill = "steelblue"),stat = "bin",stat_params = list(binwidth = 0.2))
p
ggsave("figura02.jpg")
 
p <- ggplot(dados,aes(x=preditor))
p <- p + geom_histogram(binwidth = 0.2, fill = "steelblue")
p
ggsave("figura03.jpg")
 
p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point()
p
ggsave("figura04.jpg")

Gráficos usando pacote Lattice

Opa, após um tempinho sem postagens, estou de volta. Essas últimas semanas foram meio corridas, muita coisa para fazer e não sobrou muito tempo. Mas nunca podemos parar de estudar, então aqui estamos novamente.

Recentemente eu tive que fazer alguns gráficos, de variáveis com mais de um fator, e me vi apanhando para conseguir implementar tudo que queria na figura. Eu tenho tentado aprender um pouco mais sobre ggplot2, mas ainda não sai do sistema padrão de gráficos do R.

Bem, vamos ver um exemplo aqui, e o que da para fazer.

Vamos supor que tenhamos medidas do tamanho e massa de indivíduos de uma espécie de passarinho e queremos trabalhar com a alometria dessas medidas. Mas temos essas medidas para quatro populações distintas.

Os dados são mais ou menos assim:

> head(dados) pop tamanho massa 1 1 -0.9132259 248.1997 2 1 -0.5202886 323.5949 3 1 0.2195127 300.5737 4 1 1.4554830 311.6083 5 1 -1.1484635 253.0550 6 1 1.4192977 303.5195

Então queremos ver a relação entre massa e tamanho, logo a primeira ideia que vem a cabeça é fazer um gráfico de pontos, um scatterplot entre tamanho e medida.

Como os dados estão organizadinhos como tidy-data, isso fica fácil, é usar a função plot

1
plot(massa~tamanho,data=dados)

E temos a figura.
Figura 01
01

Mas olhando os dados ali em cima, sabemos que são quatro populações diferentes, logo olhar tudo junto é no mínimo perigoso, então precisamos de algum jeito de separar elas, bem a primeira coisa que vem na minha cabeça é que podemos usar cores diferentes, ou símbolos. Como não somos limitados ao preto e branco para a simples visualização, colocamos quatro cores diferentes

1
2
plot(massa~tamanho,pch=19,frame=F,xlab="Tamanho",ylab="Massa",col=dados$pop,data=dados)
legend("topleft",pch=19,col=1:4,legend=paste("População",1:4),bty="n")

Mas como ninguém é adivinho, vamos usamos a função legend para fazer uma legenda, para ter uma associação com qual cor representa qual população, isso é importante, porque para quem sabe da onde vem os dados, isso pode trazer muito sentido, além disso podemos caprichar colocando nomes melhores nos eixos com xlab e ylab e colocar um bolinha fechada mudando o símbolo com o pch, como as populações são representadas com números aqui, usamos o col para mudar ela, apenas apontando ele para a linha do data.frame, mas se fossem palavras, o mais rápido seria usar as.numeric no vetor com os nomes.

Figura 02
02

Bem a figura ja fica mais bonitinha, mas nesse caso onde estamos colocando a massa no eixo y, temos como preditores o tamanho e a população, 2 preditores, isso pode começar a ficar confuso, então podemos na verdade quebrar a figura em quadros, ai que entra o tal das figuras do tipo lattice, o mais simples de fazer isso é alterando o argumento do par mfrow, que vai construir os gráficos por linha, ou mfcol para construir por coluna, acho que o mfrow é o mais intuitivo de usar, e mais comum nos exemplos, mas uma outra possibilidade, que eu acho interessante é usar a função layout.

No layout, a gente faz uma matriz, por exemplo:

> matrix(1:4,ncol=2,nrow=2,byrow=T) [,1] [,2] [1,] 1 2 [2,] 3 4

E isso quer dizer que vamos dividir a tela em 4 partes (número de elementos da matriz), a primeira parte vai ser do primeiro gráfico que fizermos, a segunda do segundo, e assim sucessivamente.

Então usamos informamos essa matriz para o layout:

1
layout(matrix(1:4,ncol=2,nrow=2,byrow=T))

E podemos fazer nossa figura

1
2
3
4
5
6
7
8
9
10
for(i in 1:4) {
    plot(massa~tamanho,pch=19,frame=F,xlab="Tamanho",ylab="Massa",
         col=i,data=dados[dados$pop==i,],main=paste("População",i),
         xlim=c(min(dados$tamanho),max(dados$tamanho)),
         ylim=c(min(dados$massa),max(dados$massa)) )
    ordem <- order(dados[dados$pop==i,"tamanho"])
    ajuste<-loess(massa~tamanho,dados[dados$pop==i,])
    points(ajuste$fitted[ordem]~dados[dados$pop==i,"tamanho"][ordem],
           type="l",col="red",lty=3,lwd=2)
}

Agora usamos um loop para fazer a figura, porque temos que fazer 4 gráficos, e não um so. Vamos adicionar uma linha de tendencia também usando a função loess.

Figura 03
03

E o resultado ja fica bem legal, agora so para ilustrar como o layout pode fazer coisas legais, veja que a gente pode definir a matrix de layout assim

> matrix(c(1:3,rep(4,3)),ncol=3,nrow=2,byrow=T) [,1] [,2] [,3] [1,] 1 2 3 [2,] 4 4 4

Isso quer dizer que usaremos a parte de cima da tela para os três primeiros gráficos, e a parte de baixo para o quarto, talvez não o melhor resultado, mas a ideia é que podemos repetir números para dar mais espaço a algum gráfico em detrimento do outro, basta repetir ele, usando uma matriz de quantas linhas e colunas quisermos, basta colocar os números que queremos repetindo nos espaços que devem ser dedicados ao gráfico.

Figura 04
04

Mas de modo geral, estamos reinventando a roda, como é comum a necessidade de fazer figuras desse tipo, e pode se tornar bem complicado e longo o código, levando ao erro. Mas o pacote lattice está ai para resolver, a ideia dele é ele fazer o layout e fazer os gráficos por separação de um segundo preditor.

1
2
library(lattice)
xyplot(massa~tamanho|pop,data=dados)

Então é so abrir o pacote lattice, que vem junto com o R por padrão, e separar o segundo fator por uma barrinha reta “|”, se tivermos um terceiro fator preditor, tipo espécie, será colocar “|pop+ espécie”. Mas simples assim.

Figura 05
05

Agora o que achei mais complicado no começo, foi como mexer em características dentro do plot, veja que la em cima mudávamos cor, símbolo, etc, adicionávamos linha de tendência.

Veja que coisas como

1
xyplot(massa~tamanho|pop,data=dados,pch=19,col=dados$pop)

e

1
xyplot(massa~tamanho|pop,data=dados,pch=19,col=1:4)

Vão falhar.

Figura 06
06

Bem uma diferença do lattice para o sistema de gráfico padrão do R é que no sistema padrão os gráficos a gente vai fazendo as coisas iterativamente, primeiro a gente faz o gráfico com bolinhas, depois adiciona linha de tendencia, depois faz uma legenda, depois adiciona mais pontos.

O lattice, assim como o ggplot2, é pa pum, você tem que planejar tudo, fazer o comando e mandar. Dai ele tem padrões muito legais, mas por exemplo para mudar a cor, uma possibilidade é a seguinte.

1
2
3
meu.panel = function(x,y,subscripts) {
    panel.xyplot(x,y,col=dados$pop[subscripts],pch=19)
}

Você tem que fazer sua própria função panel, a função panel é a que vai fazer a figura dentro de cada painel. Essa é a forma mais direta de você mudar o que bem entender dentro de cada painel. Existe vários panels prontos, e até argumentos que mandamos no plot que são passados para os panel padrão, mas fazer uma função panel nem é o fim do mundo. Basicamente fazemos o mesmo que fizemos dentro do loop que fizemos la em cima, mas o lattice tem copias de quase todas as funções do plot, então ao invés de usar plot, usamos panel.xyplot, e veja que o panel está recebendo três argumentos, os valores de x, de y e o subscript referentes aos dados originais, assim podemos pegar qual cor ele deve ser do vetor dados$pop.
Existem panel.points, panel.abline, acho que panel.qualquer coisa que funciona no plot, só pesquisar no help do lattice. Mas então definimos nossa função de panel e mandamos ela para o xyplot.

1
xyplot(massa~tamanho|pop,data=dados,panel=meu.panel)

Figura 07
07

Outra coisa, ao invés de usar loess, usamos panel.loess, ta tudo prontinho, na mão. Sendo que o loess já faz a linha direto, não precisamos nem ajustar o modelo e predizer os pontos com ele.

1
2
3
4
meu.panel = function(x,y,subscripts) {
    panel.xyplot(x,y,col=dados$pop[subscripts],pch=19)
    panel.loess(x, y,col="red",lty=2,lwd=2)
}

Fora isso, outras alterações comuns são querer mudar a cor, estilo do quadradinho que fica escrito o nome dos paneis, bem eu coloquei preto e branco uma vez para uma publicação, e sempre reutilizo o mesmo set, já que quase nunca quero mudar muito mais coisas mesmo.

1
trellis.par.set(strip.background=list(col="white"),box.rectangle=list(col="black"),add.text=list(font=3),box.umbrella=list(col="black"),box.dot=list(col="black"),plot.symbol=list(col="black",pch=1,cex=1))

Veja que tem parâmetros ai para mudar os boxplot feito com o irmão do xyplot que é o bwplot, que faz boxplot tipo lattice, mas isso não tem problema.

Depois de rodar ele, é so usar meu novo panel com o loess adicionado, e podemos dar configurações do strip pelo xyplot também, no caso aqui eu so vou alterar os nomes via argumento da função xyplot, isso é muito legal, para pegar configurações de gráficos bonitas que outras pessoas disponibilizam e so mudar coisas como os nomes, que são específicos.

1
2
xyplot(massa~tamanho|pop,data=dados,panel=meu.panel,xlab="Tamanho",ylab="Massa",
       strip = strip.custom(factor.levels =paste("População",1:4)))

Figura 08
08

Bem é isso ai, o script vai estar la no repositório recologia, espero do fundo do coração retormar os posts de evolução, para chegar logo a parte de invasão de espécies/fenótipos. Se eu escrevi alguma bobeira, algo errado, deixe um comentário corrigindo, ou mande um e-mail e até mais.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
library(lattice)
set.seed(1)
 
##################################
## Gerando os dados
##################################
n.grupos <- 4 # Número de populações
n.amostras <- 30 # Número de Cobras por amostras
n <- n.grupos * n.amostras # Total de amostras (Total de passarinhos)
pop <- gl(n = n.grupos, k = n.amostras) # Indicador da população
# Tamanho do corpo (cm)
tamanho.original <- runif(n, 45, 70)
mn <- mean(tamanho.original)
sd <- sd(tamanho.original)
#Mesmo que usar o comando scale(), isso faz a média ser zero
tamanho <- (tamanho.original - mn) / sd
Xmat <- model.matrix(~pop*tamanho-1-tamanho) #Aqui estamos fazendo o
#contrario que o comando formula faz, para simular uai
intercepito.mean <- 230	 # intercepto médio
intercepito.sd <- 20 # desvio dos interceptos
inclinação.mean <- 60 # inclinação média
inclinação.sd <- 30 # desvio das inclinações
intercepitos<-rnorm(n = n.grupos, mean = intercepito.mean, sd = intercepito.sd)
inclinações <- rnorm(n = n.grupos, mean = inclinação.mean, sd = inclinação.sd)
todos.os.efeitos <- c(intercepitos,inclinações) # Juntando tudo
lin.pred <- Xmat[,] %*% todos.os.efeitos # Preditores lineares
eps <- rnorm(n = n, mean = 0, sd = 30) # residuos
# resposta = preditor linear + residuo
massa <- lin.pred + eps
dados<-data.frame(pop,tamanho,massa)
#deixando somente os dados em dataframe, para acessar certo
rm(list=ls()[-1])
 
##################################
##Figuras tipo lattice
##################################
head(dados)
 
#figura 1
plot(massa~tamanho,data=dados)
 
#figura 2
plot(massa~tamanho,pch=19,frame=F,xlab="Tamanho",ylab="Massa",col=dados$pop,data=dados)
legend("topleft",pch=19,col=1:4,legend=paste("População",1:4),bty="n")
 
#figura 3
layout(matrix(1:4,ncol=2,nrow=2,byrow=T))
for(i in 1:4) {
    plot(massa~tamanho,pch=19,frame=F,xlab="Tamanho",ylab="Massa",
         col=i,data=dados[dados$pop==i,],main=paste("População",i),
         xlim=c(min(dados$tamanho),max(dados$tamanho)),
         ylim=c(min(dados$massa),max(dados$massa)) )
    ordem <- order(dados[dados$pop==i,"tamanho"])
    ajuste<-loess(massa~tamanho,dados[dados$pop==i,])
    points(ajuste$fitted[ordem]~dados[dados$pop==i,"tamanho"][ordem],
           type="l",col="red",lty=3,lwd=2)
}
 
#figura 4
layout(matrix(c(1:3,rep(4,3)),ncol=3,nrow=2,byrow=T))
for(i in 1:4) {
    plot(massa~tamanho,pch=19,frame=F,xlab="Tamanho",ylab="Massa",
         col=i,data=dados[dados$pop==i,],main=paste("População",i),
         xlim=c(min(dados$tamanho),max(dados$tamanho)),
         ylim=c(min(dados$massa),max(dados$massa)) )
    ordem <- order(dados[dados$pop==i,"tamanho"])
    ajuste<-loess(massa~tamanho,dados[dados$pop==i,])
    points(ajuste$fitted[ordem]~dados[dados$pop==i,"tamanho"][ordem],
           type="l",col="red",lty=3,lwd=2)
}
 
#figura 5
xyplot(massa~tamanho|pop,data=dados)
 
#figura 6
xyplot(massa~tamanho|pop,data=dados,pch=19,col=dados$pop)
 
#figura 7
meu.panel = function(x,y,subscripts) {
    panel.xyplot(x,y,col=dados$pop[subscripts],pch=19)
}
 
xyplot(massa~tamanho|pop,data=dados,panel=meu.panel)
 
                                        #figura 8
meu.panel = function(x,y,subscripts) {
    panel.xyplot(x,y,col=dados$pop[subscripts],pch=19)
    panel.loess(x, y,col="red",lty=2,lwd=2)
}
 
trellis.par.set(strip.background=list(col="white"),box.rectangle=list(col="black"),add.text=list(font=3),
box.umbrella=list(col="black"),box.dot=list(col="black"),plot.symbol=list(col="black",pch=1,cex=1))
 
xyplot(massa~tamanho|pop,data=dados,panel=meu.panel,xlab="Tamanho",ylab="Massa",
       strip = strip.custom(factor.levels =paste("População",1:4)))