Vários outros pacotes estão disponíveis para a geração de gráficos em R. Entre eles estão os pacotes grid
, lattice
e ggplot2
que visam expandir as habilidades do sistema gráfico básico. grid
fornece acesso de baixo nível às capacidades gráficas, geralmente usada por programadores, enquanto lattice
fornece uma abordagem intuitiva para a análise de dados multivariados. Ambos são utilizadas por outros pacotes de geração gráfica e são instaladas por padrão na instalação do de R. Focaremos aqui nossa atenção sobre ggplot2
.
Gráficos com ggplot2
ggplot2
é um pacote de visualização de dados criado por Hadley Wickham em 2005. Ele amplia e extende as funções gráficas básicas de R e contém vários padrões para exibição na web e para a impressão. O pacote é baseado no conceito de gramática de gráficos onde se pode construir todos os gráficos necessários à partir de alguns poucos componentes: o conjuntos de dados, informações para a elaboração estética do gráfico, elementos geométricos (marcas visuais para representar pontos plotados) e um sistema de coordenadas (cartesiano, polar, mapa, etc.). Apresentaremos aqui um resumo das funções. Para referências mais completas consulte os links no final este capítulo.
ggplot2
deve ser instalado separadamente ou dentro de um pacote de utilitários mais amplo que o inclui, o tidyverse
.
As partes ou componentes de um gráfico são desenhadas em camadas. Todos os gráficos plotados são iniciados com uma chamada à função ggplot()
. Em seguida, ou na mesma chamada, se fornece a fonte de dados (que deve ser um data frame) e as informações sobre a estética, especificados por aes()
. Depois são acrescentadas as camadas, escalas, coordenadas e ângulo de perspectiva, usando-se +. Gráficos são gravados em disco com a função ggsave()
. Observe que, diferente das outras funções gráficas vistas, ggplot()
não aceita vetores como argumentos mas apenas data frames.
Hadley Wickhan, em seu livro R for Data Science, propõe uma forma forma geral ou template para se compreender a estrutura de ggplot2
. Ele resume o pacote da seguinte forma:
ggplot(data = <DATA>) + <GEOM_FUNCTION> ( mapping = aes(<MAPPINGS>), stat = <STAT>, position = <POSITION> ) + <COORDINATE_FUNCTION> + <FACET_FUNCTION>
O princípio subjacente é o de que qualquer gráfico pode ser construído com esses elementos (embora nem todos sejam obrigatórios). As funções facet
permitem dividir o gráfico em partes que são plotadas juntas. É possível que em novas camadas se insira outra fonte de dados, diferente daquela passada na primeira camada.
ggplot() | Cria um gráfico |
+; %+% | operador para inserção de camadas |
aes() | insere informações sobre eixos e estética do gráfico |
ggsave() | grava um objeto ggplot |
qplot() quickplot() | plotagem simplificada |
Para ilustrar o conceito do gráfico construído por camadas considere o seguinte código:
> install.packages("tidyverse") > library(ggplot2) > data("mtcars") > g <- ggplot(mtcars) # Inicializa o gráfico > # Uma camada, contendo pontos, é inserida com geom_point. > # Em aes() mapeamos as variáveis, definimos cores e tamanho dos pontos > g <- g + geom_point(aes(x = hp, y = mpg, color = factor(am)), size = 3) > # Para alterar as cores > g <- g + scale_color_manual("Tipo", values = c("darkred", "deepskyblue4"), labels = c("Manuais", "Automáticos")) > # Rótulos > g <- g + labs(title = 'Consumo comparado de potência de carros automáticos e manuais', y = 'Consumo', x = 'Potência') > print(g)
O gráfico é plotado:
> library(ggplot2) > cidades <- data.frame(nome=c("SP", "Rio", "Bsb", "Salv", "BH"), populacao=c(12.106, 6.520, 3.040, 2.953, 2.523)) > graf <-ggplot(cidades, aes(x=nome, y=populacao)) + geom_bar(stat = "identity") + labs(title="População, em milhões") > print(graf) # gráfico-1 é plotado > # Usando mtcars$cyl como fator > a <- ggplot(mtcars, aes(factor(cyl))) > b <- a + geom_bar() > c <- a + geom_bar(fill="red") > d <- a + geom_bar(fill="red", colour = "black") > e <- a + geom_bar(fill=rainbow(3), colour = "black") > print(b) # gráfico (b) é plotado > print(c) # gráfico (c) é plotado > print(d) # gráfico (d) é plotado > print(e) # gráfico (e) é plotado
> f <- ggplot(data=mtcars, aes(x=wt, y=mpg)) + geom_point() + labs(title="Carros", x="Peso", y="Consumo: Miles/Galão") > g <- ggplot(data=mtcars, aes(x=wt, y=mpg)) + geom_point(pch=20, color="steelblue", size=2) + geom_smooth(method="lm", color="red", linetype=2) + labs(title="Automóveis", x="Peso", y="Consumo") > mtcars$am <- factor(mtcars$am, levels=c(0,1), labels=c("Automatico", "Manual")) > mtcars$vs <- factor(mtcars$vs, levels=c(0,1), labels=c("Motor-V", "Motor Comum")) > mtcars$cyl <- factor(mtcars$cyl) > h <-ggplot(data=mtcars, aes(x=hp, y=mpg, shape=cyl, color=cyl)) + geom_point(size=3) + facet_grid(am~vs) + labs(title="Carros: por tipo de motor", x="Potência", y="Consumo") > print(f) # gráfico (f) é plotado > print(g) # gráfico (g) é plotado > print(h) # gráfico (h) é plotado
Nos códigos acima ggplot()
inicializa o gráfico, informa que mtcars
será o data frame a ser usado. aes()
(que fornece a estética ou aparência do plot), mapeia o wt (peso) com o eixo x e mpg (milhas por galão, consumo) com o eixo y. Os objetos geométricos (geoms
) são os responsáveis pelos elementos visíveis sobre os eixos coordenados, incluindo pontos, linhas, barras, caixas e áreas sombreadas. No gráfico (f) geom_point()
, por padrão, marca pontos em (x, y) desenhando um gráfico de dispersão. A função labs()
insere texto para os eixos.
No gráfico (g) geom_point()
torna os pontos em esferas (pch=20), e define cor e tamanho. A função geom_smooth()
insere uma linha vermelha tracejada (linetype=2) com ajuste linear definido pelo método (method=”lm”). A área sombreada representa intervalos de 95 % de confiança (default). Os gráficos plotados são mostrados abaixo:
Em (h) são traçados gráficos separados para os tipos de transmissão automática versus manual e tipo de motor. A cor e símbolo usado indicam o número de cilindros do carro (cyl) que também é a variável agrupadora.
No último gráfico (h) as cores para o parâmetro cyl
foram escolhidas automaticamente. Para controlar manualmente este comportamento podemos usar scale_color_manual()
como exibido abaixo:
> ggplot(iris, aes(x = Petal.Length, y = Petal.Width, color = Species)) + geom_point() > ggplot(iris, aes(x = Petal.Length, y = Petal.Width, color = Species)) + geom_point() + scale_color_manual(values = c("steelblue", "gold3", "darkorange"))
Os seguintes gráficos são gerados:
A função scale_color_manual()
foi usada porque a variável Species é categórica. Outras funções são usadas para controlar escalas de cor usando diferentes tipos de variiáveis. Existem outras como scale_color__discrete()
, scale_color_continuous()
, scale_color_gradient()
, etc. Igualmente se pode controlar outras propriedades usando-se scale_fill
, scale_x
etc.
As funções geom
Através da função ggplot()
determinamos a fonte dos dados e as variáveis a serem plotadas. Já as diversas funções geom
(algumas delas listadas abaixo) informa como elas devem ser representadas graficamente.
Função | Plota | Opções |
---|---|---|
geom_bar() | gráfico de barras | color, fill, alpha |
geom_boxplot() | gráfico de caixas | color, fill, alpha, notch, width |
geom_density() | gráfico de densidades | color, fill, alpha, linetype |
geom_histogram() | histograma | color, fill, alpha, linetype, binwidth |
geom_hline() | linhas horizontais | color, alpha, linetype, size |
geom_jitter() | pontos espalhados | color, size, alpha, shape |
geom_line() | gráfico de linhas | colorvalpha, linetype, size |
geom_point() | gráfico de dispersão | color, alpha, shape, size |
geom_rug() | gráfico “rug” | color, side |
geom_smooth() | ajuste de linhas | method, formula, color, fill, linetype, size |
geom_text() | anotações em texto | Many; see the help for this function |
geom_violin() | gráfico violino | color, fill, alpha, linetype |
geom_vline() | linhas verticiais | color, alpha, linetype, size |
As opções mais comuns são:
Opção | Controla |
---|---|
color | Cor de pontos, linhas e bordas |
fill | Cor de áreas preenchidas |
alpha | transparência de cores, de 0 (transparent) até 1 (opaco) |
linetype | padrão de linhas (1 = sólido, 2 = tracejado, 3 = pontos, 4 = ponto-traço, 5 = traço longo, 6 = duplo traço) |
size | tamanho de pontos e largura de linhas |
shape | símbolo do ponto (igual pch: 0 = quadrado vazio, 1 = círculo vazio, 2 = triângulo, …) |
position | posição de objetos plotados (barras e pontos) |
binwidth | largura da caixa de histograma |
notch | booleano, se caixas devem ser recortados |
sides | colocação de “rugs” (“b” = abaixo, “l” = esquerda, “t” = acima, “r” = direita, “bl” = abaixo à esquerda, etc |
width | largura de gráficos de caixas |
Para os exemplos seguintes usaremos o data frame singer
(incluído no pacote lattice
) que contém alturas (em polegadas) e faixa vocal para cada cantor e cantora do “New York Choral Society”. As faixas são: Bass 2, Bass 1, Tenor 2, Tenor 1, Alto 2, Alto 1, Soprano 2 e Soprano 1.
> data(singer, package="lattice") > ggplot(singer, aes(x=height)) + geom_histogram(fill="red", colour = "black") + labs(title="Coral de New York", x="Altura", y="Contagem") > # O gráfico (i) é plotado > ggplot(singer, aes(x=voice.part, y=height)) + geom_boxplot(fill="steelblue", colour = "black") + labs(title="Coral de New York", x="Faixa vocal", y="Altura") > # O gráfico (j) é plotado
Note que no gráfico de histograma apenas a coordenada x foi especificada pois, nesse caso, o valor default de y é a contagem de observações incluídas dentro de cada retângulo. Como aes()
está inserido dentro de ggplot()
todos os parâmetros definidos ali serão globais, valendo para todas as camadas (se não for novamente informado dentro de outra função de camada).
Para o exemplo que se segue usaremos o data frame Salaries
que contém salários de algumas categorias de professores do ensino superior dos EUA no período de 2008-2009 (apenas 9 meses). Ele contém observações sobre algumas variáveis, incluindo sex
e salary
.
> library(car) > # Para listar o sexo em português inserimos um novo campo > Salaries$sexo <- ifelse(Salaries$sex=="Male", "Homem", "Mulher") > ggplot(Salaries, aes(x=sexo, y=salary)) + geom_boxplot(fill="skyblue3", color="black", notch=TRUE) + geom_point(color="yellow", alpha=.5) + geom_rug(sides="r", color="darkgrey") + geom_jitter(position = position_jitter(width = .1), alpha = 0.5, color="darkred") + labs(title="Salário de professores (EUA)", x="Sexo", y = "Salário")
O seguinte gráfico é plotado:
O gráfico inclui caixas chanfradas (notch) azuis com bordas pretas. Os pontos, correspondentes às observações, são plotados em amarelo, com transparência .5. Observe que todos os pontos amarelos se acumulam sobre a linha vertical correspondentes aos dois sexos, uma vez que todos possuem uma das duas coordenadas no eixo x. Uma nova camada foi inserida através de um espalhamento aleatório (jitter) sobre estes pontos, usando-se geom_jitter()
que são plotados em vermelho escuro. Este espalhamento não tem significado estatístico e serve apenas para facilitar a visualização dos pontos. Os dois conjuntos foram mantidos aqui apenas para efeito didático. Poderíamos ter inserido o efeito usando geom_point(position="jitter")
junto que os demais parâmetros e omitindo geom_jitter()
. Nesse caso os pontos amarelos ficariam dispersos. geom_rug()
insere marcas em cinza na lateral direita, correspondentes às posições (y) dos pontos. Os lados podem ser sides = "rltd"
, alguma das letras ou combinações delas: right, left, top, down.
Agrupamentos
Muitas vezes é útil observar no mesmo gráfico grupos de observações diferentes. Já vimos que podemos agrupar dados em R usando fatores (ou variáveis de categorias). No pacote ggplot2
os agrupamentos ficam definidos pela associação de variáveis com características visuais como forma, cor, preenchimento, tamanhos e tipo de linha, em geral definidas dentro da função aes()
.
> ggplot(Salaries, aes(x=rank, fill=sexo)) + geom_bar(position="stack") + labs(title='position="stack"') > ggplot(Salaries, aes(x=rank, fill=sexo)) + geom_bar(position="dodge") + labs(title='position="dodge"') > ggplot(Salaries, aes(x=rank, fill=sexo)) + geom_bar(position="fill") + labs(title='position="fill"')
O código resulta, respectivamente nos seguintes gráficos, onde o agrupamento se deu por meio do parâmetro fill
:
Mais de uma propriedade podem ser usadas para um agrupamento, como se vê no gráfico plotado pelo código abaixo.
> ggplot(data=Salaries, aes(x=salary, fill=rank)) + geom_density(alpha=.3) + labs(title="Salários de Professores", x="Salário", y="Número de Professores") ggplot(data=Salaries, aes(x=salary, fill=rank, color=sexo)) + geom_density(alpha=.3) + labs(title="Salários Masc x Fem", x="Salário", y="Número de Professores")
No segundo gráfico o agrupamento foi feito através dos parâmetros fill
e color
:
Apesar de estar pouco nítido e não muito útil para uma análise, o gráfico representa 6 distribuições diferentes para as combinações de sexo =”Masculino” e “Feminino” e rank = “Prof”, “AssistProf” e “AssocProf”. O rank está representado pelo preenchimento (fill) e o sexo pela cor da borda (color) em cada distrinuição.
Gráficos em subplos (facet
)
O último gráfico plotado apreenta 6 distribuições sobrepostas, pouco úties para uma visualização dos dados. Pode ser mais interessante analisar grupos diferentes olhando gráficos separados, apresentados lado a lado. No ggplot2
estes gráficos são chamados de facetados (faceted graphs) e são criados com as funções facet_wrap()
e facet_grid()
:
Resultado | |
---|---|
facet_wrap(~var, ncol=n) | gráficos separados para cada nível de var, dispostos em colunas |
facet_wrap(~var, nrow=n) | gráficos separados para cada nível de var, disposto em linhas |
facet_grid(rowvar~colvar) | gráficos separados para cada nível de rowvar e colvar |
facet_grid(rowvar~.) | gráficos separados para cada nível de rowvar, dispostos em uma coluna |
facet_grid(.~colvar) | gráficos separados para cada nível de colvar, dispostos em uma linha |
Na tabela var, rowvar, colvar
são fatores, rowvar
representa linhas colvar
representa colunas.
Nos exemplos abaixo usamos o mesmo gráfico congestionado do caso anterior, onde 6 distribuições estavam representadas. No primeiro caso desdobramos as plotagens em 2 linhas, separadas por sexo. No segundo 3 gráficos são dispostos em uma coluna, 3 linhas, separados por rank.
> ggplot(data=Salaries, aes(x=salary, fill=rank, color=sexo)) + geom_density(alpha=.3) + labs(title="Salários Masc x Fem", x="Salário", y="Número de Professores") + facet_wrap(~sexo, nrow=2) > ggplot(data=Salaries, aes(x=salary, fill=rank, color=sexo)) + geom_density(alpha=.3) + labs(title="Salários Masc x Fem", x="Salário", y="Número de Professores") + facet_wrap(~rank, nrow=3)
Em uma ordenação de facetas dividida por um fator com 8 elementos, distribuídos em 4 linhas, ficam dois plots lada a lado em cada linha:
> ggplot(data=singer, aes(x=height)) + geom_histogram() + labs(title="Cantores", x="Altura", y="Número de cantores") + facet_wrap(~voice.part, nrow=4)
Adicionando curvas e ajustes estatísticos
Além da construção de gráficos customizados, ggplot2
permite incluir nesses gráficos informações processadas por meio de funções estatísticas de análise. Estas funções permitem o agrupamento de dados, o cálculo de densidades, contornos e quantis. Usando a função geom_smooth()
podemos adicionar aos gráficos de dispersão linhas suavizadas (linear, não linear e não paramétricas) e sombreamentos para intervalos de confiança.
Parâmetro | Descrição |
---|---|
method= | método de suavização: lm, glm, smooth, rlm, e gam (linear, linear generalizado, loess, linear robusto ou aditivo generalizado). smooth é o default. |
formula= | fórmula para a função de suavização. Exemplos: y~x (default), y~log(x), y~poly(x,n) para ajuste a polinômio de n-ésimo grau e y~ns(x,n) para um ajuste de spline com n graus de liberdade. |
se | booleano, default=TRUE. Plota intervalos de confiança. |
level | nível para intervalos de confiança (default de 95%). |
fullrange | booleano, default=FALSE. Se o ajuste deve incluir toda a faixa do plot (TRUE) ou apenas os dados. |
LOESS suavização de dispersão estimada localmente (locally estimated scatterplot smoothing).
> library(dplyr) > carros <- mtcars %>% mutate(carro=rownames(mtcars)) > carro1 <- ggplot(carros, aes(x=disp, y=mpg)) + geom_point() + geom_smooth() > carro2 <- ggplot(data=carros, aes(x=disp, y=mpg, color=carb)) + geom_smooth(method=lm, formula=y~x, size=1) + geom_point(size=2) > carro3 <- ggplot(data=carros, aes(x=disp, y=mpg, color=carb)) + geom_smooth(method=lm, formula=y~poly(x,2), size=1) + geom_point(size=2) > carro4 <- ggplot(data=carros, aes(x=disp, y=mpg, color=carb)) + geom_smooth(method=lm, formula=y~poly(x,2), size=1, se=FALSE) + geom_point(size=2) > print(carro1) `geom_smooth()` using method = 'loess' and formula 'y ~ x' > print(carro2) > print(carro3) > print(carro4) > # os gráficos carro1, carro2, carro3 e carro4 são plotados.
Para o gráfico carro1 nenhum parâmetro foi fornecido. geom_smooth()
adotados os defaults method = 'loess', formula 'y ~ x'
, como é informado no console. Em carro2 uma reta de melhor ajuste é plotada. Em carro3 uma curva de segundo grau de melhor ajuste é plotada.
A mesma curva é repetida em carro4 sem a representação dos intervalos de confiança.
Observe que o data frame carros
foi criado à partir de mtcars
com a função mutate()
da biblioteca dplyr
. Ela permite a criação de uma nova variável para o data frame existente. Além usamos o pipe:
> mtcars %>% mutate(carro=rownames(mtcars)) > # que é o mesmo que: > mutate(mtcars, carro=rownames(mtcars))
A biblioteca ggplot2
incluiu um grande número de funções estatísticas para facilitar a visualização de dados. Estas funções podem ser chamadas implicitamente, sem chamadas do usuário. geom_smooth()
, por exemplo, faz uso de stat_smooth()
para encontrar a curva de melhor ajuste aos dados e os intervalos de confiança. É sempre útil consultar as páginas de ajuda para estas funções, por exemplo através de ?stat_smooth()
.
Temas
ggplot2
traz em sua instalação alguns temas prontos que modificam a aparência de um gráfico e a possibilidade da modificação ou criação personalizada destes temas. As opções da função theme()
permitem o ajuste de fonts, planos de fundo, cores, linhas de grade, tamanho da fonte do eixo x, posição da legenda, etc. Para cada elemento do tema existe um tipo de objeto que realiza as alterações. Por exemplo, o estilo do título do eixo x (axis.title.x) é alterado com a função element_text()
que possui diversos parâmetros (família da fonte, tipo da fonte, cor, tamanho, alinhamento etc.). As principais funções para se alterar elementos de um tema são element_text(), element_line(), element_rect() e element_blank(). O útilmo é usado para que nada seja desenhado no elemento que recebe esta função.
Um exemplo simples de uso de temas é mostrado, através da aplicação do tema theme_dark()
:
> library(lattice) # Para usar o data frame singer > ggplot(data=singer, aes(x=height, fill=voice.part)) + geom_density() + facet_grid(voice.part~.) > ggplot(data=singer, aes(x=height, fill=voice.part)) + geom_density() + facet_grid(voice.part~.) + theme_dark()
Para quem usa o RStudio existe um add-in que permite a customização gráfico do ggplot2
através de uma interface com o usuário que usa atalhos de teclado e interação com o mouse chamada ggThemeAssist
. Com ela o usuário pode alterar temas do forma WYSIWYG, usando tentativa e erro. O pacote deve ser instalado com install.packages("ggThemeAssist")
.
Para usar este add-in é necessário criar um objeto gráfico do ggplot2
e depois usá-lo como parâmetro em ggThemeAssistGadget
. Uma janela é aberta com acesso à vários elementos da geometria do gráfico. Quando a janela é fechada a função retorna uma linha de comando contendo os parâmetros para que seja plotado o gráfico escolhido. O procedimento e resultado aparecem no código abaixo.
> library(ggThemeAssist) > pp <- ggplot(data=singer, aes(x=height, fill=voice.part)) + geom_density() + facet_grid(voice.part~.) > ggThemeAssistGadget(pp) > # Uma janela é aberta onde os parâmetros podem ser alterados interativamente. > # A linha abaixo é retornada: > pp + theme(plot.subtitle = element_text(colour = "bisque4", vjust = 1), plot.caption = element_text(vjust = 1), axis.title = element_text(family = "Bookman", size = 14), plot.title = element_text(family = "Bookman"), legend.title = element_text(family = "Bookman"), panel.background = element_rect(fill = "cornsilk2"), legend.key = element_rect(colour = "antiquewhite4"), legend.background = element_rect(fill = "lavenderblush1")) + labs(title = "Número de cantores x Altura", x = "Altura", y = "Número de cantores", subtitle = "Exemplo de Uso do ggThemeAssistGadget", caption = "Gráfico demonstrativo") > # O gráfico plotado aparece na imagem abaixo.
Múltiplos gráficos por página e salvando gráficos
Para os gráficos plotados pelo sistema base de R é possível combinar vários gráficos em um único com o uso da função layout()
e o parâmetro mfrow
. Com o pacote ggplot2
gráficos podem ser combinados em uma figura única com a função grid.arrange()
.
O código ilustra este procedimento.
> install.packages("gridExtra") > library(gridExtra) > data(Salaries, package="car") > library(ggplot2) > p1 <- ggplot(data=cars, aes(x=speed)) + geom_bar(fill=rainbow(19)) > p2 <- ggplot(data=cars, aes(x=dist)) + geom_bar() > p3 <- ggplot(data=cars, aes(x=speed, y=dist)) + geom_point(color="red") > grid.arrange(p1, p2, p3, ncol=3) > ggsave(file="grafico-3.png", plot=p3, width=5, height=4) > print(p1) > ggsave(file="grafico-1.pdf")
Observe que neste caso estamos plotando gráficos independentes em uma simples figura, o que é diferente do que foi feito com a função facet
onde se representava gráficos construídos sobre um mesmo data frame mas separados por variáveis categóricas.
A função ggsave()
é usada para gravar os gráficos. A primeira chamada acima grava, na pasta ativa, uma imagem grafico-3.png
com 5×4 polegadas. A segunda, onde se omitiu o parâmetro plot
, grava um arquivo pdf com o último gráfico plotado, no caso o gráfico p1
.