Scatterplot із занадто великою кількістю очок


126

Я намагаюся побудувати дві змінні, де N = 700K. Проблема полягає в тому, що занадто багато перекриттів, так що сюжет стає в основному суцільним чорним блоком. Чи є спосіб мати «хмару» сірого кольору, де темрява ділянки є функцією кількості точок у регіоні? Іншими словами, замість того, щоб показувати окремі точки, я хочу, щоб сюжет був «хмарою», чим більше кількість пунктів у регіоні, тим темніше цей регіон.


4
Здається, ви шукаєте теплову карту: flowingdata.com/2010/01/21/…

Відповіді:


145

Один із способів вирішити це - альфа-змішування, яке робить кожну точку трохи прозорою. Тож регіони виглядають темнішими, на них накреслено більше точок.

Це легко зробити в ggplot2:

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

введіть тут опис зображення

Ще один зручний спосіб вирішити це (і, мабуть, більше підходить для кількості балів) - це шестикутне підшивання:

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

введіть тут опис зображення

А також є звичайне старе прямокутне binning (зображення опущено), що більше нагадує вашу традиційну теплову карту:

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

1
Як я можу змінити кольори? Зараз я отримую синю до чорної гами, тоді як я хотів би отримати регістр, зелену синю гаму.
користувач1007742

@ user1007742 Використовуйте scale_fill_gradient()та вкажіть свої власні низькі та високі кольори, або використовуйте scale_fill_brewer()та вибирайте одну з послідовних палітри.
joran

@joran спасибі, що працює зараз. Як щодо зміни типу / форми точок? Я отримую або шестикутник, або квадрат. Я просто хочу простих крапок. Коли я використовую geom_point (), це дає мені помилку.
користувач1007742

1
@ user1007742 Ну, це називається "шестикутна бінінг" чомусь! ;) Це не малювання "точок", це розділення всієї області на шестикутні (або прямокутні) бункери, а потім просто розфарбування бункерів залежно від кількості точок у цьому відро. Отже, коротка відповідь - "ти не можеш". Якщо ви хочете різної форми, вам потрібно використовувати geom_point()та побудувати кожну окрему точку.
joran

Що робити, якщо у мене є дані 3D?
скан

60

Ви також можете подивитися на ggsubplotпакет. Цей пакет реалізує функції, які були представлені Hadley Wickham ще в 2011 році ( http://blog.revolutionanalytics.com/2011/10/ggplot2-for-big-data.html ).

(Далі я включаю шар "точки" для ілюстрації.)

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)

введіть тут опис зображення

Однак ця функція має скелі, якщо у вас є третя змінна, для якої слід керувати.

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

введіть тут опис зображення

Або іншим підходом буде використання smoothScatter():

smoothScatter(dat[2:3])

введіть тут опис зображення


3
той другий сюжет чудовий!
Рікардо Сапорта

Що робити, якщо у мене є дані 3D?
скан

2
@ skan: Ви можете відкрити нове запитання для цього.
majom

на жаль, пакет ggsubplot вже не підтримується і видаляється з репону cran ... чи знаєте ви про альтернативний пакет, який міг би бути використаний для генерації сюжетів, як перші два вище?
dieHellste

Якщо ви користуєтеся старою версією R & ggplot2, ви повинні мати можливість спрацьовувати
19

59

Огляд кількох хороших варіантів ggplot2:

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

Варіант А: прозорі точки

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

Варіант В: додайте контури щільності

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

Варіант С: додайте контури заповненої щільності

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

Варіант D: теплова карта щільності

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

Варіант Е: гексбіни

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

Варіант F: килими

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

Об'єднайте в одну фігуру:

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

введіть тут опис зображення


1
Це дуже добре викладена відповідь, на яку я думаю, заслуговує трохи більше голосів.
Лалохезія

Повідомляє про помилку Помилка в scale_fill_viridis_c (): не вдалося знайти функцію "scale_fill_viridis_c"
JustGettinStarted

оновлений ggplot2, повторно встановлений ggplot2 та перезавантажений ggplot2. Не вдалося виправити помилку. Окремо встановлений пакунок 'viridis', який дозволив мені використовувати функцію 'scale_fill_viridis', але не функцію 'scale_fill_viridis_c', яка все ще дає ту саму помилку
JustGettinStarted

ой, я вірю тобі Ніяких питань там немає. Просто намагаюся дійти до нижньої помилки.
JustGettinStarted

51

Альфа-суміш легко зробити і з базовою графікою.

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

Перші шість цифр після #кольору є кольором у шістнадцятковій RGB, а останні два - непрозорістю, знову ж таки в шістнадцятковій, тому 33 ~ 3/16-та непрозора.

введіть тут опис зображення


20
Просто додамо трохи контексту, "# 000000" - це чорний колір, а "33", додане в кінці кольору, - ступінь непрозорості --- тут, 33%.
Чарлі

Дякую за додане пояснення.
Аарон вийшов із переповнення стека

Має ідеальний сенс. Дякую і Аарону, і Чарлі.
user702432

12
Незначна примітка; цифри є шістнадцятковими, тому 33 насправді 3/16-й непрозорий.
Аарон вийшов із переповнення стека

45

Ви також можете використовувати контурні лінії щільності ( ggplot2):

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

введіть тут опис зображення

Або комбінуйте контури густини з альфа-змішуванням:

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

введіть тут опис зображення


29

Вам може бути корисний hexbinпакет. На сторінці довідки 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 гексбін - це моє бажане рішення - він може зайняти велику кількість балів, а потім безпечно створити сюжет. Я не впевнений, що інші не намагатимуться створити сюжет, а просто затіняють речі по-іншому, як це було зроблено.
Ітератор

Щось таке, як гексбін для даних 3D?
скан

8

geom_pointdenistyз ggpointdensityпакета (нещодавно розробленого Лукасом Кремером та Саймоном Андерсом (2019)) дозволяє візуалізувати щільність та окремі точки даних одночасно:

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

Мій улюблений метод побудови такого типу даних - той, який описаний у цьому питанні - графік щільності розсіювання . Ідея полягає в тому, щоб зробити розкидний графік, але забарвити точки за їх щільністю (грубо кажучи, величиною накладання в цій області).

Це одночасно:

  • чітко показує місце розташування людей, що вижили, та
  • розкриває будь-яку структуру на щільній ділянці ділянки.

Ось результат головної відповіді на пов’язане питання:

Діаграма щільності розсіювання


1
Це теж мій улюблений спосіб. Дивіться мою відповідь, як цього досягти R.
jan-glx
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.