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.

user702432
źródło
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()
joran
źródło
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

majom
źródło
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

Axeman
źródło
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

Aaron opuścił Stack Overflow
źródło
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

ROLO
źródło
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

Oscar Perpiñán
źródło
+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()

jan-glx
źródło
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

Stephen McAteer
źródło
1
To też jest mój ulubiony sposób. Zobacz moją odpowiedź, jak to osiągnąć w R.
jan-glx