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.