2016-01-27 9 views
6

ostatecznego wdrożenia - nie skończył, ale pozycja właściwa drogaDziałka/ggplot2 - Wypełnij obszar ze zbyt wielu punktów

idea/Problem: masz działkę z wielu nakładających się punktów i chcą je zastąpić obszar prosty, co zwiększa wydajność wyświetlania działki.

Możliwe wdrożenie: Oblicz macierz odległości między wszystkimi punktami i połącz wszystkie punkty poniżej określonej odległości.

Todo/Not finished: Ten aktualnie działa dla ręcznie ustawionych odległości w zależności od wielkości drukowanego wykresu. Zatrzymałem się tutaj, ponieważ wynik nie spełnił mojego estetycznego zmysłu.

minimalna przykład przy powierzchniach pośrednich

set.seed(074079089) 
n.points <- 3000 

mat <- matrix(rnorm(n.points*2, 0,0.2), nrow=n.points, ncol=2) 
colnames(mat) <- c("x", "y") 

d.mat <- dist(mat) 
fit.mat <-hclust(d.mat, method = "single") 
lims <- c(-1,1) 
real.lims <- lims*1.1    ## ggplot invokes them approximately 

# An attempt to estimate the point-sizes, works for default pdfs pdf("test.pdf") 
cutsize <- sum(abs(real.lims))/100 
groups <- cutree(fit.mat, h=cutsize) # cut tree at height cutsize 
# plot(fit.mat) # display dendogram 

# draw dendogram with red borders around the 5 clusters 
# rect.hclust(fit.mat, h=cutsize, border="red") 

library(ggplot2) 
df <- data.frame(mat) 
df$groups <- groups 
plot00 <- ggplot(data=df, aes(x,y, col=factor(groups))) + 
    geom_point() + guides(col=FALSE) + xlim(lims) + ylim(lims)+ 
    ggtitle("Each color is a group") 
pdf("plot00.pdf") 
print(plot00) 
dev.off() 

plot00 - points with group color

# If less than 4 points are connected, show them seperately 
t.groups <- table(groups) # how often which group 
drop.group <- as.numeric(names(t.groups[t.groups<4])) # groups with less than 4 points are taken together 
groups[groups %in% drop.group] <- 0      # in group 0 
df$groups <- groups 
plot01 <- ggplot(data=df, aes(x,y, col=factor(groups))) + 
    geom_point() + xlim(lims)+ ylim(lims) + 
    scale_color_hue(l=10) 
pdf("plot01.pdf") 
print(plot01) 
dev.off() 

plot01 - all single points in one group

find_hull <- function(df_0) 
{ 
    return(df_0[chull(df_0$x, df_0$y), ]) 
} 


library(plyr) 
single.points.df <- df[df$groups == 0 , ] 
connected.points.df <- df[df$groups != 0 , ] 
hulls <- ddply(connected.points.df, "groups", find_hull) # for all groups find a hull 
plot02 <- ggplot() + 
    geom_point(data=single.points.df, aes(x,y, col=factor(groups))) + 
    xlim(lims)+ ylim(lims) + 
    scale_color_hue(l=10) 
pdf("plot02.pdf") 
print(plot02) 
dev.off() 

plot02 - only "single"-points (less than 4 connected points)

plot03 <- plot02 
for(grp in names(table(hulls$groups))) 
{ 
    plot03 <- plot03 + geom_polygon(data=hulls[hulls$groups==grp, ], 
            aes(x,y), alpha=0.4) 
} 
# print(plot03) 
plot01 <- plot01 + theme(legend.position="none") 
plot03 <- plot03 + theme(legend.position="none") 
# multiplot(plot01, plot03, cols=2) 
pdf("plot03.pdf") 
print(plot03) 
dev.off() 

plot03 - final

początkowe pytanie

mam (może nieparzyste) pytanie.

W niektórych działkach mam tysiące punktów w mojej analizie. Aby je wyświetlić, komputer zajmuje sporo czasu, ponieważ jest tak wiele punktów. Później wiele z tych punktów może się pokrywać, mam wypełniony obszar (co jest w porządku!). Aby zaoszczędzić czas/wysiłek wyświetlania, dobrze byłoby po prostu wypełnić ten obszar, ale wykreślając każdy punkt na własną rękę.

Wiem, że są możliwości w mapach termicznych i tak dalej, ale nie o to mi chodzi. Mój pomysł jest taki:

#plot00: ggplot with many many points and a filled area of points 
plot00 <- plot00 + fill.crowded.areas() 

# with plot(), I sadly have an idea how to manage it 

Jakieś pomysły? Czy to nic, co każdy zrobiłby w dowolnym momencie?

# Example code 
# install.packages("ggplot2") 
library(ggplot2) 

n.points <- 10000 
mat <- matrix(rexp(n.points*2), nrow=n.points, ncol=2) 
colnames(mat) <- c("x", "y") 
df <- data.frame(mat) 
plot00 <- ggplot(df, aes(x=x, y=y)) + 
    theme_bw() +      # white background, grey strips 
    geom_point(shape=19)# Aussehen der Punkte 

print(plot00) 

ggplot2

# NO ggplot2 
plot(df, pch=19) 

plot

Edit:
Aby Density-działek jak wspomniano przez fdetsch (jak mogę zaznaczyć nazwę?) Istnieją pewne pytania dotyczące tego produktu temat. Ale to nie jest to, czego chcę dokładnie. Wiem, że moja troska jest nieco dziwna, ale gęstość sprawia, że ​​w razie potrzeby fabuła staje się bardziej zajęta.

Linki do tematów z gęstościach:

Scatterplot with too many points
High Density Scatter Plots

+0

co prosisz jest trudne, ponieważ renderowanie stały blok zależy od parametrów graficznych (np. wielkości punktu), które wybierasz. Aby utworzyć obszary bryłowe, należy buforować punkty w jedną warstwę w taki sam sposób, jak system informacji geograficznej - [to pytanie] (https://stackoverflow.com/questions/25411251/buffer-geospatial-points-in-r -with-gbuffer) może pomóc. – geotheory

Odpowiedz

1

można użyć solidnego prognozy oszacować położenie większość swojego punkty i wykreślić wypukły kadłub punktów w następujący sposób:

set.seed(1337) 
n.points <- 500 
mat <- matrix(rexp(n.points*2), nrow=n.points, ncol=2) 
colnames(mat) <- c("x", "y") 
df <- data.frame(mat) 

require(robustbase) 
my_poly <- function(data, a, ...){ 
    cov_rob = covMcd(data, alpha = a) 
    df_rob = data[cov_rob$best,] 
    ch = chull(df_rob$x, df_rob$y) 
    geom_polygon(data = df_rob[ch,], aes(x,y), ...) 
} 

require(ggplot2) 
ggplot() + 
    geom_point(data=df, aes(x,y)) + 
    my_poly(df, a = 0.5, fill=2, alpha=0.5) + 
    my_poly(df, a = 0.7, fill=3, alpha=0.5) 

Prowadzi to do:

enter image description here

kontrolując wartość alfa covMcd można zwiększyć/zmniejszyć rozmiar obszaru. Aby uzyskać szczegółowe informacje, patrz ?robustbase::covMcd. Btw .: Mcd oznacza minimalną kowariancję Determinant. Zamiast tego można również użyć parametru MASS::cov.mve do obliczenia minimalnej wartości elipsoidy z wartością MASS::cov.mve(..., quantile.used= -punkt punktów w elipsoidzie.

Dla 2+ klas:

my_poly2 <- function(data, a){ 
    cov_rob = covMcd(data, alpha = a) 
    df_rob = data[cov_rob$best,] 
    ch = chull(df_rob[,1], df_rob[,2]) 
    df_rob[ch,] 
} 

ggplot(faithful, aes(waiting, eruptions, color = eruptions > 3)) + 
    geom_point() + 
    geom_polygon(data = my_poly2(faithful[faithful$eruptions > 3,], a=0.5), aes(waiting, eruptions), fill = 2, alpha = 0.5) + 
    geom_polygon(data = my_poly2(faithful[faithful$eruptions < 3,], a=0.5), aes(waiting, eruptions), fill = 3, alpha = 0.5) 

enter image description here

Lub jeśli jesteś ok z un-solidna elipsoidy przyjrzeć się stat_ellipse

+0

fajny pomysł, ale co, jeśli mam 2+ obszary? – groebsgr

+0

Spójrz na moją edycję – Rentrop

+0

, która wydaje się całkiem dobra, spróbuję w następnym momencie, w tej chwili jest zbyt dużo rzeczy do zrobienia, ale prawdopodobnie dam ostateczną implementację jak to zrobiłem. Dziękujemy! – groebsgr

4

Jak na temat korzystania panel.smoothScatter z siatkowej? Wyświetla pewną liczbę punktów w regionach o niskiej gęstości (patrz argument "nrpoints"), a wszędzie indziej gęstości punktów są wyświetlane zamiast pojedynczych (i prawdopodobnie nakładających się) punktów, zapewniając w ten sposób bardziej wnikliwy wgląd w dane. Dodatkowe informacje można znaleźć również pod adresem ?panel.smoothScatter.

## load 'lattice' 
library(lattice) 

## display point densities 
xyplot(y ~ x, data = df, panel = function(x, y, ...) { 
    panel.smoothScatter(x, y, nbin = 250, ...) 
}) 

enter image description here

+0

Jestem świadomy tego "kreślenia gęstości", to miło, moim zdaniem, ale nie o to mi chodzi. (przepraszam: D) - niemniej jednak! – groebsgr

1

Czy masz na myśli coś takiego jak convex hull swoich punktów:

Convex Hull of points

set.seed(1337) 
n.points <- 100 
mat <- matrix(rexp(n.points*2), nrow=n.points, ncol=2) 
colnames(mat) <- c("x", "y") 
df <- data.frame(mat) 
ch <- chull(df$x, df$y) # This computes the convex hull 

require(ggplot2) 
ggplot() + 
    geom_point(data=df, aes(x,y)) + 
    geom_polygon(data = df[ch,], aes(x,y), alpha=0.5) 
+0

Próbowałem teraz przez około 20 minut. To mogło! doprowadzić do wyniku, jaki chcę. Najpierw chcę zamienić punkty poniżej wielokąta. Po drugie, jak znajdę połączone obszary? Może matryca odległości i tylko małe odległości dla wielokąta? – groebsgr