2013-04-24 22 views
11

Eksperymentuję ze sposobami radzenia sobie z overplottingiem w R, a jedną rzeczą, którą chcę spróbować, jest wyrysowanie poszczególnych punktów, ale zabarwienie ich gęstością ich sąsiedztwa. W tym celu musiałbym obliczyć oszacowanie gęstości jądra 2D w każdym punkcie. Wydaje się jednak, że standardowe funkcje estymacji gęstości jądra są oparte na siatce. Czy istnieje funkcja obliczania oszacowań gęstości jądra 2D w określonych punktach, które określam? Wyobrażam sobie funkcję, która pobiera wektory x i y jako argumenty i zwraca wektor oszacowań gęstości.Jak mogę uzyskać wartość oszacowania gęstości jądra w określonych punktach?

+0

Czy istnieje szczególny powód, dla którego mieszanie alpha lub bardziej standardowe metody binowania (takie jak binowanie heksagonalne) nie są wystarczające? – joran

+1

Chcę, aby wartości odstające były wyraźnie widoczne jako pojedyncze punkty. Pękanie alfa sprawia, że ​​wystające części są słabe, a sześciokątne binning zamienia je w całe sześciokąty zamiast pojedynczych punktów. Ocena gęstości jądra na całej siatce dobrze sprawdza się w przypadku większości danych, ale wszystkie punkty odstające zmieniają się w małe gaussowskie "pufy", więc chcę zamiast tego obliczyć oszacowanie gęstości jądra i użyć go do przypisania koloru do każdego punktu . W ten sposób uzyskalibyśmy w zasadzie taki sam wygląd, jak podejście oparte na siatce, gdzie wiele punktów nakłada się, ale spowodowałoby, że wartości odstające byłyby wyraźnie widoczne jako punkty dyskretne. –

Odpowiedz

4

W końcu znalazłem dokładną funkcję, której szukałem: interp.surface z pakietu fields. Z tekstu pomocy:

Wykorzystuje wagi dwuliniowe do interpolacji wartości na prostokątnej siatce do dowolnych lokalizacji lub do innej siatki.

+1

Wiem, że to jest stare ... ale czy 'fields :: interp.surface' działa dla ciebie? To nie działa dla mnie z powyższym przykładem zabawek, ponieważ wymiary nie pasują do danych wyjściowych 'newdata' i' interp.surface'. Zobacz http://stackoverflow.com/questions/43896337/use-fieldsinterp-surface-to-interpolate-from-grid-to-irregular-points. – bstock

5

Jeśli dobrze rozumiem, co chcesz zrobić, może to zostać osiągnięte poprzez dopasowanie modelu wygładzania do oszacowania gęstości siatki, a następnie przy użyciu tego przewidzieć gęstość w każdym punkcie jesteś zainteresowany. Na przykład:

# Simulate some data and put in data frame DF 
n <- 100 
x <- rnorm(n) 
y <- 3 + 2* x * rexp(n) + rnorm(n) 
# add some outliers 
y[sample(1:n,20)] <- rnorm(20,20,20) 
DF <- data.frame(x,y) 

# Calculate 2d density over a grid 
library(MASS) 
dens <- kde2d(x,y) 

# create a new data frame of that 2d density grid 
# (needs checking that I haven't stuffed up the order here of z?) 
gr <- data.frame(with(dens, expand.grid(x,y)), as.vector(dens$z)) 
names(gr) <- c("xgr", "ygr", "zgr") 

# Fit a model 
mod <- loess(zgr~xgr*ygr, data=gr) 

# Apply the model to the original data to estimate density at that point 
DF$pointdens <- predict(mod, newdata=data.frame(xgr=x, ygr=y)) 

# Draw plot 
library(ggplot2) 
ggplot(DF, aes(x=x,y=y, color=pointdens)) + geom_point() 

enter image description here

Lub jeśli po prostu zmienić n 10^6 otrzymujemy

enter image description here

+0

Tak, dokładnie tego chciałem. Dzięki! –

+0

W rzeczywistości model less może spowodować nadmierne wygładzenie wartości. Gęstość jądra już się wygładza. Czy istnieje sposób, aby po prostu zastosować dwuliniową (lub bikubiczną) interpolację z wartości siatki? –

+0

Jeśli ostrożnie ustawisz parametr rozpiętości na lessowy na dość niską wartość, dostaniesz zachowanie, które chcesz, myślę. Mogą być też inne sposoby. –