2014-02-19 11 views
12

In einer previous question habe ich ein Konturplot reproduziert, das mit dem Feld packages in ggplot2 generiert wurde (vollständiges Beispiel unten). Das einzige Problem ist, ich möchte die Platzierung der Kontur-Etiketten in contour() replizieren, die standardmäßig auf der "flachsten" Teil der Linie sind - das zweite Bild könnte warum zeigen. Ich bin ratlos, wie ich diese Berechnung einstelle. Ich sehe here, dass es möglich ist, die Daten zu nehmen, die verwendet werden, um die Höhenlinien zu generieren, und dann geom_text() könnte verwendet werden, um den Text zu plotten. Was bleibt, ist herauszufinden, wie man den "flachsten" Teil berechnet. Ideen?Zeichnen von Beschriftungen auf flachen Abschnitten von Konturlinien in ggplot2

library(fields) 
library(ggplot2) 
library(reshape) 
library(directlabels) 

sumframe<-structure(list(Morph = c("LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW"), xvalue = c(4, 8, 9, 9.75, 13, 14, 16.25, 17.25, 18, 23, 27, 28, 28.75, 4, 8, 9, 9.75, 13, 14, 16.25, 17.25, 18, 23, 27, 28, 28.75), yvalue = c(17, 34, 12, 21.75, 29, 7, 36.25, 14.25, 24, 19, 36, 14, 23.75, 17, 34, 12, 21.75, 29, 7, 36.25, 14.25, 24, 19, 36, 14, 23.75), zvalue = c(126.852666666667, 182.843333333333, 147.883333333333, 214.686666666667, 234.511333333333, 198.345333333333, 280.9275, 246.425, 245.165, 247.611764705882, 266.068, 276.744, 283.325, 167.889, 229.044, 218.447777777778, 207.393, 278.278, 203.167, 250.495, 329.54, 282.463, 299.825, 286.942, 372.103, 307.068)), .Names = c("Morph", "xvalue", "yvalue", "zvalue"), row.names = c(NA, -26L), class = "data.frame") 

sumframeLW<-subset(sumframe, Morph=="LW") 

# FIELDS CONTOUR PLOT: 
surf.teLW<-Tps(cbind(sumframeLW$xvalue, sumframeLW$yvalue), sumframeLW$zvalue, lambda=0.01) 
summary(surf.teLW) 
surf.te.outLW<-predict.surface(surf.teLW) 
image(surf.te.outLW, col=tim.colors(128), xlim=c(0,38), ylim=c(0,38), zlim=c(100,400), lwd=5, las=1, font.lab=2, cex.lab=1.3, mgp=c(2.7,0.5,0), font.axis=1, lab=c(5,5,6), xlab=expression("X value"), ylab=expression("Y value"),main="LW plot") 
contour(surf.te.outLW, lwd=2, labcex=1, add=T) 

FieldsContourPlot.jpg

# GGPLOT2 CONTOUR PLOT: 
LWsurfm<-melt(surf.te.outLW) 
LWsurfm<-rename(LWsurfm, c("value"="z", "X1"="x", "X2"="y")) 
LWsurfms<-na.omit(LWsurfm) 

LWp<-ggplot(LWsurfms, aes(x,y,z=z))+geom_tile(aes(fill=z))+stat_contour(aes(x,y,z=z, colour=..level..), colour="black", size=0.6)+scale_fill_gradientn(colours=tim.colors(128)) 
LWp 
LWp<-direct.label(LWp) 

ggplotContourPlot.jpg

Antwort

3

hat ich eine Funktion, um den flachste Abschnitt unter Verwendung des Verfahrens für contour() (von plot3d) zu berechnen, einen Datenrahmen mit nur den flachsten Werten mit Hilfe von plyr erstellt wird, und hinzugefügt, um es von Hand in das Stück mit geom_text(). Um exakt die Ausgabe contour() zu erreichen, müssen die Etiketten gedreht werden, Abschnitte der Konturlinien müssen gelöscht werden, um Platz für die Etiketten zu schaffen, und Korrekturen müssen vorgenommen werden, um sicherzustellen, dass die Etiketten nicht von den Kanten der Kontur fallen Linien. Ich werde in den nächsten Monaten daran arbeiten (das ist alles noch ein Nebenprojekt).

library(fields) 
library(ggplot2) 
library(reshape) 

sumframe<-structure(list(Morph = c("LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "LW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW"), xvalue = c(4, 8, 9, 9.75, 13, 14, 16.25, 17.25, 18, 23, 27, 28, 28.75, 4, 8, 9, 9.75, 13, 14, 16.25, 17.25, 18, 23, 27, 28, 28.75), yvalue = c(17, 34, 12, 21.75, 29, 7, 36.25, 14.25, 24, 19, 36, 14, 23.75, 17, 34, 12, 21.75, 29, 7, 36.25, 14.25, 24, 19, 36, 14, 23.75), zvalue = c(126.852666666667, 182.843333333333, 147.883333333333, 214.686666666667, 234.511333333333, 198.345333333333, 280.9275, 246.425, 245.165, 247.611764705882, 266.068, 276.744, 283.325, 167.889, 229.044, 218.447777777778, 207.393, 278.278, 203.167, 250.495, 329.54, 282.463, 299.825, 286.942, 372.103, 307.068)), .Names = c("Morph", "xvalue", "yvalue", "zvalue"), row.names = c(NA, -26L), class = "data.frame") 

# Subdivide, calculate surfaces, recombine for ggplot: 
sumframeLW<-subset(sumframe, Morph=="LW") 
sumframeSW<-subset(sumframe, Morph="SW") 

surf.teLW<-Tps(cbind(sumframeLW$xvalue, sumframeLW$yvalue), sumframeLW$zvalue, lambda=0.01) 
surf.te.outLW<-predict.surface(surf.teLW) 

surf.teSW<-Tps(cbind(sumframeSW$xvalue, sumframeSW$yvalue), sumframeSW$zvalue, lambda=0.01) 
surf.te.outSW<-predict.surface(surf.teSW) 

sumframe$Morph<-as.numeric(as.factor(sumframe$Morph)) 

LWsurfm<-melt(surf.te.outLW) 
LWsurfm<-rename(LWsurfm, c("value"="z", "X1"="x", "X2"="y")) 
LWsurfms<-na.omit(LWsurfm) 
LWsurfms[,"Morph"]<-c("LW") 

SWsurfm<-melt(surf.te.outSW) 
SWsurfm<-rename(SWsurfm, c("value"="z", "X1"="x", "X2"="y")) 
SWsurfms<-na.omit(SWsurfm) 
SWsurfms[,"Morph"]<-c("SW") 

LWSWsurf<-rbind(LWsurfms, SWsurfms) 
# Note that I've lost my units - things have been rescaled to be between 0 and 80. 

LWSWc<-ggplot(LWSWsurf, aes(x,y,z=z))+facet_wrap(~Morph)+geom_contour(colour="black", size=0.6) 
LWSWc 
# Create data frame from data used to generate this contour plot: 
tmp3<-ggplot_build(LWSWc)$data[[1]] 

Auf den Punkt gebracht, die tmp3 Datenrahmen enthält einen Vektor, tmp3$group, die als eine Gruppenvariable für nachfolgende Berechnungen verwendet wurde. Innerhalb jeder Stufe von tmp3$group wurden die Varianzen mit flattenb berechnet. Ein neuer Datenrahmen wurde erzeugt, und die Werte von diesem Datenrahmen wurden zu dem Diagramm mit geom_text() hinzugefügt.

flattenb <- function (tmp3){ 
    counts = length(tmp3$group) 
    xdiffs = diff(tmp3$x) 
    ydiffs = diff(tmp3$y) 
    avgGradient = ydiffs/xdiffs 
    squareSum = avgGradient * avgGradient 
    variance = (squareSum - (avgGradient * avgGradient)/counts/counts) 
    data.frame(variance = c(9999999, variance) #99999 pads this so the length is same as original and the first values are not selected 
    ) 
} 

tmp3<-cbind(tmp3, ddply(tmp3, 'group', flattenb)) 
tmp3l<-ddply(tmp3, 'group', subset, variance==min(variance)) 
tmp3l[,"Morph"]<-c(rep("LW", times=8), rep("SW", times=8)) 

LWSWpp<-ggplot(LWSWsurf, aes(x,y,z=z)) 
LWSWpp<-LWSWpp+geom_tile(aes(fill=z))+stat_contour(aes(x,y,z=z, colour=..level..), colour="black", size=0.6) 
LWSWpp<-LWSWpp+scale_fill_gradientn(colours=tim.colors(128)) 
LWSWpp<-LWSWpp+geom_text(data=tmp3l, aes(z=NULL, label=level))+facet_wrap(~Morph) 
LWSWpp 

PlotOfPositionedLabels

+0

Mit dem 'LWSWsurf' Datenrahmen und dem Kommentar von Baptiste, das ist näher an dem, wonach ich suche, obwohl es immer noch nicht so schön aussieht wie ich ' d wie: 'levelplot (z ~ x * y | Morph, Daten = LWSWsurf, Kontur = TRUE, label.style =" align ", pretty = WAHR, col.regions = tim.colors (128), labels = TRUE)' – rebeccmeister

1

Sie müssen den Algorithmus implementieren von hier:

https://github.com/wch/r-source/blob/c3ba5b0be36d3a1290e18fe189142c88f1e43236/src/library/graphics/src/plot3d.c#L1668

die Funktion zurückgeben keine Informationen über die Position des die Contou r Etiketten, es macht die eigentliche Zeichnung auf dem Grafikgerät, so dass Sie es nicht in ggplot einhaken können. Es weiß auch, die Konturlinie nicht unter dem Label zu zeichnen.

Bis dies in ggplot implementiert ist, bleiben Sie mit den Basisgrafiken.

+0

Danke für den Link. Ich bleibe bei den Basisgrafiken, außer: (1) Maßstabsbalkenverhalten in Basisgrafiken macht es schwierig, mehrere Diagramme sauber auf einer Seite zu kombinieren, und (2) Ich konstruiere Multiplot-Bilder von Konturdiagrammen plus facettiert (ggplot2) oder Spalier (Gitter) Plots. Wenn ich nur Konturdiagramme graphisch zeichne, funktioniert 'set.screen' gut mit der Maßstabsleiste auf dem eigenen Bildschirm. ggplot2 + base funktioniert in Ordnung mit einer Modifikation der Methode [hier] (http://stackoverflow.com/questions/14124373/combine-base-and-ggplot-graphics-in-r-figure-window), aber Maßstabsbalken bekommen wieder peinlich. – rebeccmeister

+1

der Algorithmus ist auch implementiert in 'gitter :: panel.levelplot' – baptiste

+0

@baptiste ich bin nicht davon überzeugt - Kontur verwendet einen minimalen Wigglinity-Punkt, wobei panel.levelplot nach dem horizontalen Punkt mit minimaler Steigung (für seine 'flach' Algorithmus). – Spacedman

Verwandte Themen