Wykres rozrzutu ze zbyt dużą liczbą punktów


126

Próbuję wykreślić dwie zmienne, gdzie N = 700K. Problem polega na tym, że nakładanie się jest zbyt duże, więc działka staje się przeważnie jednolitym blokiem czerni. Czy istnieje sposób na stworzenie „chmury” w skali szarości, w której ciemność wykresu jest funkcją liczby punktów w regionie? Innymi słowy, zamiast pokazywać poszczególne punkty, chcę, aby wykres był „chmurą”, przy czym im większa liczba punktów w regionie, tym ciemniejszy jest ten region.


4
Wygląda na to, że szukasz mapy popularności

Odpowiedzi:


145

Jednym ze sposobów rozwiązania tego problemu jest mieszanie alfa, które sprawia, że ​​każdy punkt jest lekko przezroczysty. Zatem regiony wydają się ciemniejsze, na których naniesiono więcej punktów.

Można to łatwo zrobić w ggplot2:

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

wprowadź opis obrazu tutaj

Innym wygodnym sposobem radzenia sobie z tym jest (i prawdopodobnie bardziej odpowiedni do liczby posiadanych punktów) jest binowanie heksagonalne:

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

wprowadź opis obrazu tutaj

Istnieje również zwykły stary binning prostokątny (obraz pominięty), który bardziej przypomina tradycyjną mapę cieplną:

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

1
Jak mogę zmienić kolory? Teraz otrzymuję skalę od niebieskiego do czarnego, podczas gdy chciałbym uzyskać reg, zielono-niebieską skalę.
user1007742

@ user1007742 Użyj scale_fill_gradient()i określ własne niskie i wysokie kolory lub użyj scale_fill_brewer()i wybierz jedną z kolejnych palet.
joran

@joran dzięki, to teraz działa. Co powiesz na zmianę typu / kształtu punktów? Dostaję sześciokąt lub kwadrat. Chcę tylko prostych kropek. Kiedy używam geom_point (), wyświetla mi się błąd.
user1007742

1
@ user1007742 Nie bez powodu nazywa się to „binningiem sześciokątnym”! ;) To nie jest kreślenie "punktów", to dzielenie całego regionu na sześciokątne (lub prostokątne) kosze, a następnie po prostu kolorowanie koszy w oparciu o liczbę punktów w tym koszu. Więc krótka odpowiedź brzmi „nie możesz”. Jeśli chcesz mieć różne kształty, musisz użyć geom_point()i wykreślić każdy punkt.
joran

A jeśli mam dane 3D?
skan

60

Możesz też rzucić okiem na ggsubplotopakowanie. Ten pakiet zawiera funkcje, które zostały zaprezentowane przez Hadleya Wickhama w 2011 roku ( http://blog.revolutionanalytics.com/2011/10/ggplot2-for-big-data.html ).

(W dalszej części dołączam warstwę „punktów” dla celów ilustracyjnych).

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)

wprowadź opis obrazu tutaj

Jednak ta funkcja oferuje skały, jeśli masz trzecią zmienną do kontrolowania.

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

wprowadź opis obrazu tutaj

Lub innym podejściem byłoby użycie smoothScatter():

smoothScatter(dat[2:3])

wprowadź opis obrazu tutaj


3
ta druga fabuła jest świetna!
Ricardo Saporta

A jeśli mam dane 3D?
skan

2
@ skan: Możesz otworzyć w tym celu nowe pytanie.
majom

niestety pakiet ggsubplot nie jest już konserwowany i usunięty z repozytorium Cran ... czy znasz alternatywny pakiet, który mógłby zostać użyty do wygenerowania wykresów, takich jak dwa pierwsze powyżej?
dieHellste

Jeśli używasz starej wersji R & ggplot2, powinieneś móc ją
uruchomić

59

Przegląd kilku dobrych opcji w ggplot2:

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

Opcja A: przezroczyste punkty

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

Opcja B: dodaj kontury gęstości

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

Opcja C: dodaj wypełnione kontury gęstości

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

Opcja D: mapa cieplna gęstości

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

Opcja E: hexbins

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

Opcja F: dywaniki

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

Połącz w jedną figurę:

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

wprowadź opis obrazu tutaj


1
Jest to bardzo ładna odpowiedź, która moim zdaniem zasługuje na nieco więcej pozytywnych głosów.
Lalochezia

Daje mi błąd Błąd w scale_fill_viridis_c (): nie można znaleźć funkcji "scale_fill_viridis_c"
JustGettinRozpoczęto

zaktualizowano ggplot2, ponownie zainstalowałem ggplot2 i załadowano ponownie ggplot2. Nie naprawiono błędu. Oddzielnie zainstalowany pakiet `` viridis '', który pozwala mi użyć funkcji `` scale_fill_viridis '', ale nie funkcji `` scale_fill_viridis_c '', która nadal powoduje ten sam błąd
JustGettin rozpoczął się

och, wierzę ci. Żadnych problemów. Próbuję tylko dotrzeć do sedna błędu.
JustGettin rozpoczął się

51

Mieszanie alfa jest łatwe również w przypadku grafiki podstawowej.

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

Sześć pierwszych cyfr po znaku #to kolor w zapisie szesnastkowym RGB, a ostatnie dwie to krycie, ponownie w formacie szesnastkowym, czyli 33 ~ 3/16 nieprzezroczystości.

wprowadź opis obrazu tutaj


20
Żeby dodać trochę kontekstu, „# 000000” to kolor czarny, a „33” dodane na końcu koloru to stopień krycia - tutaj 33%.
Charlie,

Dzięki za dodatkowe wyjaśnienie.
Aaron opuścił Stack Overflow

To ma sens. Dzięki, zarówno Aaron, jak i Charlie.
user702432

12
Drobna uwaga; liczby są w zapisie szesnastkowym, więc 33 to w rzeczywistości 3/16 nieprzezroczysty.
Aaron opuścił Stack Overflow

45

Możesz również użyć linii konturów gęstości ( ggplot2):

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

wprowadź opis obrazu tutaj

Lub połącz kontury gęstości z mieszaniem alfa:

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

wprowadź opis obrazu tutaj


29

hexbinPakiet może okazać się przydatny . Ze strony pomocy 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 to moje preferowane rozwiązanie - może zająć dużą liczbę punktów, a następnie bezpiecznie utworzyć wykres. Nie jestem pewien, czy inni nie będą próbowali tworzyć fabuły, ale po prostu odcień rzeczy inaczej ex post.
Iterator

Coś jak hexbin dla danych 3D?
skan

8

geom_pointdenistyz ggpointdensitypakietu (ostatnio opracowanego przez Lukasa Kremera i Simona Andersa (2019)) umożliwia jednoczesną wizualizację gęstości i poszczególnych punktów danych:

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

Moją ulubioną metodą wykreślania tego typu danych jest ta opisana w tym pytaniu - wykres gęstości rozproszenia . Chodzi o to, aby wykonać wykres punktowy, ale pokolorować punkty według ich gęstości (z grubsza mówiąc, stopień nakładania się w tym obszarze).

Jednocześnie:

  • wyraźnie pokazuje lokalizację wartości odstających i
  • odsłania jakąkolwiek strukturę w zwartym obszarze działki.

Oto wynik najwyższej odpowiedzi na pytanie, do którego prowadzi łącze:

wykres gęstości rozproszenia


1
To też jest mój ulubiony sposób. Zobacz moją odpowiedź, jak to osiągnąć w R.
jan-glx
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.