2016-01-15 12 views
7

Używam ggtern do wykreślenia dużego zbioru danych w postaci trzeciorzędnego wykresu (patrz poniżej przykład).Wykreślanie wyników kde w ggtern

enter image description here

Aż pewnego dane size wszystko było idealne, ponieważ używałem geom_density_tern(). Ponieważ chcę wizualizować znacznie bardziej skomplikowany zestaw danych ładujący go cały czas, a rendering z ggplot staje się niemożliwy (ograniczenie po stronie pamięci). Pomyślałem, że być może może istnieć obejście przez przypisanie wyniku macierzy kde2d obliczonej oddzielnie. I właśnie tam utknąłem. Chciałbym wiedzieć, czy można to zrobić w jakikolwiek sposób w ggtern?

W każdym razie dodam minimalny przypadek struktury danych i kreślenia, których używam w tej chwili.

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 

Te dodatkowe linie odtworzyć wykres gęstości w potrójnego systemu koordynacji:

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

i uzyskaniu tego wykresu:

enter image description here

Z góry dzięki za wszelką pomoc!

+0

Czy dobrze rozumiem, że można zadzwonić 'kde2', ale z pamięcią na' ggtern + geom_density_tern'? – tonytonov

+0

Miałem na myśli to, że w mojej "prawdziwej" analizie mam ogromną ramkę danych, która jest daleko do dużej wartości dla geom_density_tern do obsługi za jednym razem. Myślałem o wczytaniu w geom_density_tern wcześniej obliczonej macierzy kde2. Czy jest to bardziej zrozumiałe? – Ludwik

Odpowiedz

2

Możemy rozwiązać ten problem za pomocą kodu, który jest zwykle używany za kulisami w statystyce. Właśnie wydałem ggtern 2.0.1, opublikowany na CRAN kilka dni temu po całkowitym przepisaniu pakietu, aby był zgodny z ggplot2 2.0.0, znam podejście, które może odpowiadać twoim potrzebom. Nawiasem mówiąc, dla Państwa zainteresowania, podsumowanie nowej funkcji w ggtern 2.0.X można znaleźć here:

Poniżej znajduje się rozwiązanie i działający kod dla twojego problemu, który jest oszacowaniem gęstości obliczonym na podstawie stosunku izometrycznego.

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

Dzięki za to rozwiązanie. Dodałem wiersz biblioteki (skala), ponieważ bez niego funkcja expand_range() była niedostępna. – Ludwik

+0

Nadal występuje problem z wykreślaniem danych, ale w tym celu otworzę nowy wątek. – Ludwik

+0

Przykro mi, zapomniałem dodać wagi, miałem to załadowane z czegoś innego. Jaki jest dodatkowy problem? –