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.


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

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


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


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


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


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


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


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


1
Ini juga cara favorit saya. Lihat jawaban saya untuk cara mencapai ini di R.
jan-glx
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.