Построение результата kde в ggtern
Я использую ggtern для построения большого набора данных в виде третичного графика (см. Пример ниже).
До определенного размера данных все было идеально, так как я использовал 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")
И получить этот график:
Заранее благодарю за любую помощь!
1 ответ
Мы можем решить эту проблему, используя код, который обычно используется за кулисами в Stat. Только что выпустив ggtern 2.0.1
опубликованный на CRAN пару дней назад после полного переписывания пакета для совместимости с ggplot2 2.0.0
Я знаком с подходом, который может удовлетворить ваши потребности. Кстати, для вашего интереса, краткое описание новых функций в ggtern 2.0.X
можно найти здесь:
Ниже, пожалуйста, найдите решение и рабочий код для вашей проблемы, который является оценкой плотности, рассчитанной в изометрическом логарифмическом пространстве.
#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")