Scatterplot dengan poin terlalu banyak

126

Saya mencoba untuk memplot dua variabel di mana N = 700K. Masalahnya adalah ada terlalu banyak tumpang tindih, sehingga plot menjadi sebagian besar blok hitam. Apakah ada cara untuk memiliki "awan" abu-abu di mana kegelapan plot adalah fungsi dari jumlah titik di suatu wilayah? Dengan kata lain, alih-alih menunjukkan poin individu, saya ingin plot menjadi "awan", dengan semakin banyak poin di suatu wilayah, semakin gelap wilayah itu.

pengguna702432
sumber
4
Kedengarannya seperti Anda sedang mencari peta panas

Jawaban:

145

Salah satu cara untuk mengatasi ini adalah dengan alpha blending, yang membuat setiap titik sedikit transparan. Jadi daerah tampak lebih gelap yang memiliki lebih banyak titik diplot pada mereka.

Ini mudah dilakukan di ggplot2:

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

masukkan deskripsi gambar di sini

Cara lain yang mudah untuk menangani ini adalah (dan mungkin lebih tepat untuk jumlah poin yang Anda miliki) adalah binning heksagonal:

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

masukkan deskripsi gambar di sini

Dan ada juga binning persegi panjang biasa (gambar dihilangkan), yang lebih mirip peta panas tradisional Anda:

ggplot(df,aes(x=x,y=y)) + geom_bin2d()
joran
sumber
1
Bagaimana saya bisa mengubah warna? Sekarang saya mendapatkan skala biru ke hitam, sedangkan saya ingin mendapatkan skala hijau skala reg.
user1007742
@ user1007742 Gunakan scale_fill_gradient()dan tentukan sendiri warna rendah dan tinggi Anda, atau gunakan scale_fill_brewer()dan pilih dari salah satu palet berurutan.
joran
@ Terima kasih joran, itu berfungsi sekarang. Bagaimana dengan mengubah jenis / bentuk poin? Saya mendapatkan segi enam atau persegi. Saya hanya ingin titik-titik sederhana. Ketika saya menggunakan geom_point (), itu memberi saya kesalahan.
user1007742
1
@ user1007742 Yah, itu disebut "binning heksagonal" karena suatu alasan! ;) Itu tidak merencanakan "titik" itu membagi seluruh wilayah menjadi nampan heksagonal (atau persegi panjang) dan kemudian hanya mewarnai nampan berdasarkan berapa banyak titik dalam nampan itu. Jadi jawaban singkatnya adalah "Anda tidak bisa". Jika Anda menginginkan bentuk yang berbeda, Anda harus menggunakan geom_point()dan memplot setiap titik individual.
joran
Bagaimana jika saya memiliki data 3D?
skan
60

Anda juga dapat melihat ggsubplotpaketnya. Paket ini mengimplementasikan fitur-fitur yang disajikan oleh Hadley Wickham pada tahun 2011 ( http://blog.revolutionanalytics.com/2011/10/ggplot2-for-big-data.html ).

(Berikut ini, saya memasukkan "poin" -pemain untuk tujuan ilustrasi.)

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)

masukkan deskripsi gambar di sini

Namun, fitur ini mengguncang jika Anda memiliki variabel ketiga untuk dikontrol.

# 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)  

masukkan deskripsi gambar di sini

Atau pendekatan lain adalah menggunakan smoothScatter():

smoothScatter(dat[2:3])

masukkan deskripsi gambar di sini

majom
sumber
3
plot kedua itu hebat!
Ricardo Saporta
Bagaimana jika saya memiliki data 3D?
skan
2
@ skan: Anda dapat membuka pertanyaan baru untuk itu.
majom
sayangnya paket ggsubplot tidak dirawat lagi dan dihapus dari cran repo ... apakah Anda tahu paket alternatif yang dapat digunakan untuk menghasilkan plot seperti dua yang pertama di atas?
dieHellste
Jika Anda menggunakan versi lama R & ggplot2, Anda seharusnya dapat membuatnya berfungsi
majom
59

Ikhtisar beberapa opsi bagus di ggplot2:

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

Opsi A: titik transparan

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

Opsi B: tambahkan kontur kerapatan

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

Opsi C: tambahkan kontur kerapatan yang terisi

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

Opsi D: peta panas kerapatan

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')

Opsi E: hexbins

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

Opsi F: permadani

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

Gabungkan dalam satu gambar:

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

masukkan deskripsi gambar di sini

Axeman
sumber
1
Ini adalah jawaban yang ditata dengan sangat baik yang menurut saya layak mendapat lebih banyak suara.
Lalochezia
Memberi saya kesalahan Kesalahan pada scale_fill_viridis_c (): tidak dapat menemukan fungsi "scale_fill_viridis_c"
JustGettin Mulai
memperbarui ggplot2, menginstal ulang ggplot2 dan memuat ulang ggplot2. Tidak memperbaiki kesalahan. Paket 'viridis' yang terinstal secara terpisah dan yang memungkinkan saya menggunakan fungsi 'scale_fill_viridis' tetapi bukan fungsi 'scale_fill_viridis_c' yang masih memberikan kesalahan yang sama
JustGettin Mulai
oh saya percaya kamu. Tidak ada masalah di sana. Hanya mencoba untuk sampai ke dasar kesalahan.
JustGettin Mulai
51

Alpha blending juga mudah dilakukan dengan grafis dasar.

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

Enam angka pertama setelah #adalah warna dalam RGB hex dan dua terakhir adalah opacity, lagi-lagi dalam hex, jadi 33 ~ 3/16 buram.

masukkan deskripsi gambar di sini

Aaron meninggalkan Stack Overflow
sumber
20
Hanya untuk menambahkan sedikit konteks, "# 000000" adalah warna hitam dan "33" yang ditambahkan ke akhir warna adalah tingkat kekeruhan --- di sini, 33%.
Charlie
Terima kasih atas penjelasan yang ditambahkan.
Aaron meninggalkan Stack Overflow
Masuk akal. Terima kasih, baik Harun dan Charlie.
user702432
12
Catatan kecil; angka-angka dalam hex jadi 33 sebenarnya 3/16 buram.
Aaron meninggalkan Stack Overflow
45

Anda juga dapat menggunakan garis kontur kerapatan ( ggplot2):

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

masukkan deskripsi gambar di sini

Atau kombinasikan kontur kerapatan dengan alpha blending:

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

masukkan deskripsi gambar di sini

ROLO
sumber
29

Anda mungkin menemukan hexbinpaket yang bermanfaat. Dari halaman bantuan 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

Oscar Perpiñán
sumber
+1 hexbin adalah solusi pilihan saya - ini dapat mengambil banyak # poin dan kemudian membuat plot dengan aman. Saya tidak yakin yang lain tidak akan mencoba membuat plot, tetapi hanya menaungi hal-hal yang berbeda secara ex post.
Iterator
Apa pun seperti hexbin untuk data 3D?
skan
8

geom_pointdenistyfrom the ggpointdensitypackage (baru-baru ini dikembangkan oleh Lukas Kremer dan Simon Anders (2019)) memungkinkan Anda memvisualisasikan kerapatan dan titik data individual pada saat yang sama:

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()

jan-glx
sumber
2

Metode favorit saya untuk memplot tipe data ini adalah yang dijelaskan dalam pertanyaan ini - plot sebaran-kerapatan . Idenya adalah untuk melakukan sebar-plot tetapi untuk mewarnai titik dengan kepadatan mereka (secara kasar, jumlah tumpang tindih di daerah itu).

Secara bersamaan:

  • jelas menunjukkan lokasi outlier, dan
  • mengungkapkan setiap struktur di area padat plot.

Ini adalah hasil dari jawaban teratas untuk pertanyaan terkait:

plot sebaran-kepadatan

Stephen McAteer
sumber
1
Ini juga cara favorit saya. Lihat jawaban saya untuk cara mencapai ini di R.
jan-glx