Gráfico de dispersão com muitos pontos


126

Estou tentando plotar duas variáveis ​​em que N = 700K. O problema é que há muita sobreposição, de modo que a trama se torna principalmente um sólido bloco de preto. Existe alguma maneira de ter uma "nuvem" em escala de cinza em que a escuridão da trama é uma função do número de pontos em uma região? Em outras palavras, em vez de mostrar pontos individuais, quero que o gráfico seja uma "nuvem", com o número de pontos em uma região, mais escura será a região.


4
Parece que você está procurando um mapa de calor: flowdata.com/2010/01/21/…

Respostas:


145

Uma maneira de lidar com isso é com a mistura alfa, que torna cada ponto um pouco transparente. Portanto, as regiões parecem mais escuras e com mais pontos traçados nelas.

Isso é fácil de fazer em ggplot2:

df <- data.frame(x = rnorm(5000),y=rnorm(5000))
ggplot(df,aes(x=x,y=y)) + geom_point(alpha = 0.3)

insira a descrição da imagem aqui

Outra maneira conveniente de lidar com isso é (e provavelmente mais apropriado para o número de pontos que você possui) é o bin hexagonal:

ggplot(df,aes(x=x,y=y)) + stat_binhex()

insira a descrição da imagem aqui

E também há binning retangular antigo regular (imagem omitida), que é mais parecido com o seu mapa de calor tradicional:

ggplot(df,aes(x=x,y=y)) + geom_bin2d()

1
Como posso mudar as cores? Agora estou ficando azul para preto, enquanto eu gostaria de obter reg, verde azul escala.
— user1007742

@ user1007742 Use scale_fill_gradient()e especifique suas próprias cores baixa e alta, ou use scale_fill_brewer()e escolha uma das paletas seqüenciais.
— joran

@ obrigado obrigado, isso está funcionando agora. Que tal mudar o tipo / forma dos pontos? Eu recebo hexágono ou quadrado. Eu só quero pontos simples. Quando eu uso geom_point (), isso me dá erro.
— user1007742

1
@ user1007742 Bem, é chamado de "compartimento hexagonal" por um motivo! ;) Não está plotando "pontos", está dividindo toda a região em compartimentos hexagonais (ou retangulares) e, em seguida, simplesmente colorindo os compartimentos com base em quantos pontos existem nesse compartimento. Portanto, a resposta curta é "você não pode". Se você quiser formas diferentes, precisará usar geom_point()e plotar cada ponto individual.
— joran

E se eu tiver dados 3D?
— skan

60

Você também pode dar uma olhada no ggsubplotpacote. Este pacote implementa os recursos apresentados por Hadley Wickham em 2011 ( http://blog.revolutionanalytics.com/2011/10/ggplot2-for-big-data.html ).

(A seguir, incluo a camada "points" para fins de ilustração.)

library(ggplot2)
library(ggsubplot)

# Make up some data
set.seed(955)
dat <- data.frame(cond = rep(c("A", "B"), each=5000),
                  xvar = c(rep(1:20,250) + rnorm(5000,sd=5),rep(16:35,250) + rnorm(5000,sd=5)),
                  yvar = c(rep(1:20,250) + rnorm(5000,sd=5),rep(16:35,250) + rnorm(5000,sd=5)))


# Scatterplot with subplots (simple)
ggplot(dat, aes(x=xvar, y=yvar)) +
  geom_point(shape=1) +
  geom_subplot2d(aes(xvar, yvar,
                     subplot = geom_bar(aes(rep("dummy", length(xvar)), ..count..))), bins = c(15,15), ref = NULL, width = rel(0.8), ply.aes = FALSE)

insira a descrição da imagem aqui

No entanto, esse recurso é ótimo se você tiver uma terceira variável para controlar.

# Scatterplot with subplots (including a third variable) 

ggplot(dat, aes(x=xvar, y=yvar)) +
  geom_point(shape=1, aes(color = factor(cond))) +
  geom_subplot2d(aes(xvar, yvar,
                     subplot = geom_bar(aes(cond, ..count.., fill = cond))),
                 bins = c(15,15), ref = NULL, width = rel(0.8), ply.aes = FALSE)  

insira a descrição da imagem aqui

Ou outra abordagem seria usar smoothScatter():

smoothScatter(dat[2:3])

insira a descrição da imagem aqui


3
esse segundo enredo é ótimo!
— Ricardo Saporta

E se eu tiver dados 3D?
— skan

2
@ skan: Você pode abrir uma nova pergunta para isso.
— majom

infelizmente, o pacote ggsubplot não é mais mantido e removido do repositório do cran ... você conhece um pacote alternativo que poderia ser usado para gerar gráficos como os dois primeiros acima?
— dieHellste

Se você usar uma versão antiga do R & ggplot2, você deve ser capaz de fazê-lo funcionar
— majom

59

Uma visão geral de várias boas opções em ggplot2:

library(ggplot2)
x <- rnorm(n = 10000)
y <- rnorm(n = 10000, sd=2) + x
df <- data.frame(x, y)

Opção A: pontos transparentes

o1 <- ggplot(df, aes(x, y)) +
  geom_point(alpha = 0.05)

Opção B: adicione contornos de densidade

o2 <- ggplot(df, aes(x, y)) +
  geom_point(alpha = 0.05) +
  geom_density_2d()

Opção C: adicione contornos de densidade preenchidos

o3 <- ggplot(df, aes(x, y)) +
  stat_density_2d(aes(fill = stat(level)), geom = 'polygon') +
  scale_fill_viridis_c(name = "density") +
  geom_point(shape = '.')

Opção D: mapa de calor de densidade

o4 <- ggplot(df, aes(x, y)) +
  stat_density_2d(aes(fill = stat(density)), geom = 'raster', contour = FALSE) +       
  scale_fill_viridis_c() +
  coord_cartesian(expand = FALSE) +
  geom_point(shape = '.', col = 'white')

Opção E: hexbins

o5 <- ggplot(df, aes(x, y)) +
  geom_hex() +
  scale_fill_viridis_c() +
  geom_point(shape = '.', col = 'white')

Opção F: tapetes

o6 <- ggplot(df, aes(x, y)) +
  geom_point(alpha = 0.1) +
  geom_rug(alpha = 0.01)

Combine em uma figura:

cowplot::plot_grid(
  o1, o2, o3, o4, o5, o6,
  ncol = 2, labels = 'AUTO', align = 'v', axis = 'lr'
)

insira a descrição da imagem aqui


1
Esta é uma resposta muito bem definida que eu acho que merece um pouco mais de votos.
— Lalochezia 26/03

Dá-me um erro Erro em scale_fill_viridis_c (): não foi possível encontrar a função "scale_fill_viridis_c"
— JustGettinStarted

atualizado ggplot2, reinstalado o ggplot2 e recarregado o ggplot2. Não corrigiu o erro. Pacote 'viridis' instalado separadamente e que me permita usar a função 'scale_fill_viridis', mas não a função 'scale_fill_viridis_c' que ainda dá o mesmo erro
— JustGettinStarted

oh eu acredito em você. Não há problemas lá. Apenas tentando chegar ao fundo do erro.
— usar o seguinte código

51

A mistura alfa também é fácil com os gráficos básicos.

df <- data.frame(x = rnorm(5000),y=rnorm(5000))
with(df, plot(x, y, col="#00000033"))

Os seis primeiros números após o #são a cor em hexadecimal RGB e os dois últimos são a opacidade, novamente em hexadecimal, de modo 33 a 3 / 16º opaco.

insira a descrição da imagem aqui


20
Apenas para adicionar um pouco de contexto, "# 000000" é a cor preta e o "33" adicionado ao final da cor é o grau de opacidade --- aqui, 33%.
— Charlie

Obrigado pela explicação adicionada.
— Aaron saiu de Stack Overflow

Faz todo o sentido. Obrigado, Aaron e Charlie.
— user702432

12
Nota menor; os números estão em hexadecimal, então 33 é na verdade 1/16 de opaco.
— Aaron saiu de Stack Overflow

45

Você também pode usar linhas de contorno de densidade ( ggplot2):

df <- data.frame(x = rnorm(15000),y=rnorm(15000))
ggplot(df,aes(x=x,y=y)) + geom_point() + geom_density2d()

insira a descrição da imagem aqui

Ou combine contornos de densidade com mistura alfa:

ggplot(df,aes(x=x,y=y)) + 
    geom_point(colour="blue", alpha=0.2) + 
    geom_density2d(colour="black")

insira a descrição da imagem aqui


29

Você pode achar útil o hexbinpacote. Na página de ajuda de hexbinplot:

library(hexbin)
mixdata <- data.frame(x = c(rnorm(5000),rnorm(5000,4,1.5)),
                      y = c(rnorm(5000),rnorm(5000,2,3)),
                      a = gl(2, 5000))
hexbinplot(y ~ x | a, mixdata)

hexbinplot


O hexbin com +1 é minha solução preferida - ele pode levar um grande número de pontos e criar um gráfico com segurança. Não tenho certeza de que os outros não tentem produzir um enredo, mas simplesmente sombreie as coisas de maneira diferente ex post.
— Iterator

Algo como hexbin para dados 3D?
— skan

8

geom_pointdenistydo ggpointdensitypacote (desenvolvido recentemente por Lukas Kremer e Simon Anders (2019)) permite visualizar a densidade e os pontos de dados individuais ao mesmo tempo:

library(ggplot2)
# install.packages("ggpointdensity")
library(ggpointdensity)

df <- data.frame(x = rnorm(5000), y = rnorm(5000))
ggplot(df, aes(x=x, y=y)) + geom_pointdensity() + scale_color_viridis_c()


2

Meu método favorito para plotar esse tipo de dados é o descrito nesta pergunta - um gráfico de densidade de dispersão . A idéia é fazer um gráfico de dispersão, mas colorir os pontos de acordo com sua densidade (grosso modo, a quantidade de sobreposição nessa área).

Simultaneamente:

  • mostra claramente a localização dos outliers e
  • revela qualquer estrutura na área densa da trama.

Aqui está o resultado da resposta principal à pergunta vinculada:

gráfico de densidade de dispersão


1
Esta é a minha maneira favorita também. Veja minha resposta sobre como conseguir isso em R.
— jan-GLX
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.