Визуализация большого набора точек с третьей функцией в виде цвета - способ повысить скорость - PullRequest
0 голосов
/ 21 октября 2018

У меня довольно большой набор данных (около 5e5 строк) с координатами (x, y) с дополнительной функцией z.Это примерно так:

x <- rnorm(1e6, 0, 5)
y <- rnorm(1e6, 0, 10)
dist <- sqrt(x^2 + y^2)
z <- exp(-(dist / 8)^2)

Я хочу построить их с помощью функции z, используемой в качестве эстетики цвета.Но простой geom_point занимает некоторое время с таким большим набором данных:

data.frame(x, y, z) %>% 
  ggplot() + geom_point(aes(x, y, color = z)) 

enter image description here

Так что я думаю, что мне нужен способ агрегирования точек в некоторыхпуть.Один из подходов состоит в том, чтобы разделить плоскость на несколько маленьких квадратов и усреднить все значения z для точек, лежащих в квадрате.Но это может быть немного громоздким в долгосрочной перспективе, и, вероятно, лучше использовать некоторые из уже доступных инструментов.Поэтому я подумал о geom_hex как о geom, который будет хорошо выглядеть в моем случае.Но fill эстетика по умолчанию настроена на count.Итак, мои вопросы:

  • Можно ли по умолчанию fill значение geom_hex легко изменить на среднее значение z?
  • Если нет, то как я могу создать шестиугольники вместо квадратов, чтобы значение z можно было усреднить по шестиугольникам и затем построить?
  • Есть ли другой способ улучшить скорость построения графиков?такой набор данных?

Редактировать:

Сравнение предложенных решений:

library(microbenchmark)
microbenchmark(
  'stat_summary_hex' = {data.frame(x, y, z) %>%                                                                                                   
    ggplot( aes(x, y, z=z )) + stat_summary_hex(fun = function(x) mean(x))},
  'round_and_group' = {data.frame(x, y, z) %>%                                                   
      mutate(x=round(x, 0), y=round(y, 0)) %>%                                  
      group_by(x,y) %>%                                                         
      summarize(z = mean(z)) %>%                                                
      ggplot() + geom_hex(aes(x, y, fill = z), stat="identity")}
)

Unit: milliseconds
             expr        min        lq       mean     median        uq        max neval
 stat_summary_hex   2.243791   2.38539   2.454039   2.426123   2.50871   2.963176   100
  round_and_group 183.785828 186.38851 188.296828 187.347476 189.10874 218.668487   100

Ответы [ 4 ]

0 голосов
/ 29 октября 2018

Когда размеры наборов данных становятся большими, может быть стоит перейти на специализированное программное обеспечение.Например, datashader может рисовать цветные точечные диаграммы больших наборов данных за разумное время.Однако в настоящее время он не имеет интерфейса R (только Python).

0 голосов
/ 25 октября 2018

Может быть, это может помочь stat_summary_hex() или stat_summary_2d().

Они похожи на stat_summary(), данные разделены в ячейки с x и y, а затем суммированы по z, используя функцию, указанную в stat_summary_hex() (или stat_summary_2d()).

library(tidyverse)
data.frame(x, y, z) %>%  
# here you can specify the function that welcomes the z parameter                                                                                              
ggplot( aes(x, y, z=z )) + stat_summary_hex(fun = function(x) mean(x))

enter image description here

Он ответит на ваш второй вопрос(шестнадцатеричный) и ваш третий вопрос (кажется, хорошо с производительностью, как вы заявили), вместо использования geom_hex() (так что, кажется, есть торговля между geom_hex() и скоростью).

РЕДАКТИРОВАТЬ

Глядя на ваши вопросы, я микробенчмаркировал функцию с различными значениями:

Unit: milliseconds
  expr      min       lq     mean   median       uq       max neval
 3.5e5 205.0363 214.6925 236.8149 225.2286 238.6536  494.7897   100
   1e6 575.4861 597.4161 665.4396 620.9151 702.1622 1143.7011   100

Кроме того, вы также можете указать ячейки, чтобы иметь больше или меньше "точные гексы.Значение по умолчанию должно быть 30, это означает, что он собирается построить точки в области 30 * 30 гексов:

data.frame(x, y, z) %>%                                                                                            
ggplot( aes(x, y, z=z )) + stat_summary_hex(fun = function(x) mean(x), bins = 60)

Как пример ( здесь функция multiplot(), еслинеобходимо):

set.seed(1)
x <- rnorm(1e4, 0, 5)                                                     
y <- rnorm(1e4, 0, 10)                                                    
dist <- sqrt(x^2 + y^2)                                                   
z <- exp(-(dist / 8)^2) 

library(tidyverse)

a1 <- data.frame(x, y, z) %>% 
      ggplot() + geom_point(aes(x, y, color = z)) 

b1 <- data.frame(x, y, z) %>%  
     ggplot( aes(x, y, z=z )) + stat_summary_hex(fun = function(x) mean(x))

c1 <- data.frame(x, y, z) %>%  
      ggplot( aes(x, y, z=z )) + stat_summary_hex(fun = function(x) mean(x), bins = 60)

multiplot(a1,b1,c1, cols = 3)

enter image description here

Как видите, чем больше вы добавляете гексов, тем больше вы приближаетесь к исходным точкам.


С данными:

x <- rnorm(1e4, 0, 5)                                                     
y <- rnorm(1e4, 0, 10)                                                    
dist <- sqrt(x^2 + y^2)                                                   
z <- exp(-(dist / 8)^2) 
0 голосов
/ 26 октября 2018

Вы можете рассмотреть возможность использования растров для этого:

library(raster)
library(rasterVis)

p = data.frame(x, y, z)
coordinates(p) = ~x+y

r = raster(nrows=500, ncols=500, ext = extent(c(range(c(x,y)), range(c(x,y)))), crs=CRS("+init=epsg:28992"))
r = rasterize(p, r, 'z', fun=mean)
levelplot(r)

enter image description here

NB Если вы не хотите использовать RasterVis, вы можете строить графики с помощью ggplotили базовая графика, если вы предпочитаете.Например, с помощью ggplot мы можем сделать

ggplot(as.data.frame(r, xy = TRUE) ) +
  geom_raster(aes(x, y, fill = layer)) +
  scale_fill_continuous(na.value="white")

enter image description here

0 голосов
/ 21 октября 2018

stat="identity" используется на столбчатых / столбчатых диаграммах для использования значения вместо счетчика.Это похоже на работу с geom_hex

library(dplyr)                                                            
library(ggplot2)                                                          
x <- rnorm(1e4, 0, 5)                                                     
y <- rnorm(1e4, 0, 10)                                                    
dist <- sqrt(x^2 + y^2)                                                   
z <- exp(-(dist / 8)^2)                                                   

##  Summarize to rounded x and y, calculate mean(z), use stat = "identity"
data.frame(x, y, z) %>%                                                   
mutate(x=round(x, 0), y=round(y, 0)) %>%                                  
group_by(x,y) %>%                                                         
summarize(z = mean(z)) %>%                                                
ggplot() + geom_hex(aes(x, y, fill = z), stat="identity")                 

...