2016-01-15 3 views
7

Я использую ggtern для построения большого набора данных в форме третичного сюжета (см. Пример ниже).Построение результата kde в ggtern

enter image description here

До определенного размера данных все было идеально, как я использовал geom_density_tern(). Поскольку я хочу визуализировать гораздо более сложный набор данных, загружая все это, а рендеринг с ggplot становится невозможным (ограничение на стороне памяти). Я подумал, что, возможно, может возникнуть обходное решение, введя в расчет результат вычисления матрицы kde2d отдельно. И вот где я застрял. Я хотел бы знать, можно ли это сделать в ggtern?

В любом случае я добавляю минимальный случай структуры данных и чертежей, которые я использую в данный момент.

require(ggplot2) 
require(ggtern) 

set.seed(1) 

mydata <- data.frame(
     x = runif(100, min = 0.25, max = 0.5), 
     y = runif(100, min = 0.1, max = 0.4), 
     z = runif(100, min = 0.5, max = 0.7)) 

plot <- ggtern() + 
     theme_bw() + 
     theme_hidetitles() + 
     geom_density_tern(data = mydata, 
      aes(x = x, y = y, z = z, alpha = ..level..), 
      size = 0.1, linetype = "solid", fill = "blue")+ 
     geom_point(data = mydata, 
      aes(x = x, y = y, z = z), alpha = 0.8, size = 1) 
plot 

Эти дополнительные линии воспроизводят график плотности в тройной системе координации:

library(MASS) 
dataTern = transform_tern_to_cart(mydata$x,mydata$y,mydata$z) 
dataTernDensity <- kde2d(x=dataTern$x, y=dataTern$y, lims = c(range(0,1), range(0,1)), n = 400) 

image(dataTernDensity$x, dataTernDensity$y, dataTernDensity$z) 
points(dataTern$x, dataTern$y, pch = 20, cex = 0.1) 
segments(x0 = 0, y0 = 0, x1 = 0.5, y1 = 1, col= "white") 
segments(x0 = 0, y0 = 0, x1 = 1, y1 = 0, col= "white") 
segments(x0 = 0.5, y0 = 1, x1 = 1, y1 = 0, col= "white") 

И получить этот график:

enter image description here

Спасибо заранее за любую помощь!

+0

Правильно ли я понимаю, что вы можете назвать 'kde2', но из памяти' ggtern + geom_density_tern'? – tonytonov

+0

Я имел в виду, что в моем «реальном» анализе у меня есть огромный фрейм данных, который очень большой для geom_density_tern для обработки за один раз. Я решил загрузить в geom_density_tern предварительно рассчитанную матрицу kde2. Это более понятно? – Ludwik

ответ

2

Мы можем решить это, используя код, который обычно используется за кулисами в Stat. Только что выпущенный ggtern 2.0.1, опубликованный на CRAN пару дней назад после полной перезаписи пакета, совместимого с ggplot2 2.0.0, я знаком с подходом, который может удовлетворить ваши потребности. Кстати, для вас интереса, резюме новой функциональности в ggtern 2.0.X можно найти here:

Ниже пожалуйста найти решение и рабочий код для вашей проблемы, которая является оценкой плотности в расчете на изометрическом логарифмическом отношении пространства.

solution

#Required Libraries 
library(ggtern) 
library(ggplot2) 
library(compositions) 
library(MASS) 
library(scales) 

set.seed(1) #For Reproduceability 
mydata <- data.frame(
    x = runif(100, min = 0.25, max = 0.5), 
    y = runif(100, min = 0.1, max = 0.4), 
    z = runif(100, min = 0.5, max = 0.7)) 

#VARIABLES 
nlevels = 7 
npoints = 200 
expand = 0.5 

#Prepare the data, put on isometric logratio basis 
df  = data.frame(acomp(mydata)); colnames(df) = colnames(mydata) 
data = data.frame(ilr(df)); colnames(data) = c('x','y') 

#Prepare the Density Estimate Data 
h.est = c(MASS::bandwidth.nrd(data$x), MASS::bandwidth.nrd(data$y)) 
lims = c(expand_range(range(data$x),expand),expand_range(range(data$y),expand)) 
dens = MASS::kde2d(data$x,data$y,h=h.est,n=npoints,lims=lims) 

#------------------------------------------------------------- 
#<<<<< Presumably OP has data at this point, 
#  and so the following should achieve solution 
#------------------------------------------------------------- 

#Generate the contours via ggplot2's non-exported function 
lines = ggplot2:::contour_lines(data.frame(expand.grid(x = dens$x, y = dens$y), 
              z=as.vector(dens$z),group=1), 
           breaks=pretty(dens$z,n=nlevels)) 

#Transform back to ternary space 
lines[,names(mydata)] = data.frame(ilrInv(lines[,names(data)])) 

#Render the plot 
ggtern(data=lines,aes(x,y,z)) + 
    theme_dark() + 
    theme_legend_position('topleft') + 
    geom_polygon(aes(group=group,fill=level),colour='grey50') + 
    scale_fill_gradient(low='green',high='red') + 
    labs(fill = "Density", 
     title = "Example Manual Contours from Density Estimate Data") 
+0

Спасибо за это решение. Я добавил библиотеку (шкалы), так как без нее функция expand_range() отсутствовала. – Ludwik

+0

По-прежнему существует проблема с построением данных, но для этого я открою новый поток. – Ludwik

+0

Извините, забыли включить весы, я загрузил его из чего-то другого. Какая дополнительная проблема? –