2016-09-25 4 views
3

Ich versuche ein Tiefenprofil-Diagramm mit den Variablen Tiefe, Abstand und Temperatur zu erstellen. Die gesammelten Daten stammen von 9 verschiedenen Punkten mit bekannten Abständen zwischen ihnen (Distanz 5m, 9 Stationen, 9 verschiedene Datensätze). Die Temperaturmesswerte entsprechen diesen 9 Stationen, wo eine Sonde direkt nach unten fallen gelassen wurde, wobei die Temperatur alle 2 Sekunden gemessen wurde. Die maximale Tiefe an jeder der 9 Stationen wurde ebenfalls vom Boot genommen.Tiefenprofilierung Visualisierung

so dass die Daten ich habe, ist:

  1. Tiefe an jeder der Stationen 9 (y-Achse)
  2. Temperaturwerte an jeder der Stationen 9, bei etwa .2m Abständen senkrecht bis der Boden war erreicht (Ausfüllbereich)
  3. Entfernung zwischen den Stationen, (x-Achse)

Ist es möglich, ein Tiefenprofil ähnlich wie diese zu schaffen? (Natürlich ohne die größere Auflösung in dieser Grafik)

enter image description here

Ich habe bereits versucht Herumspielen mit ggplot2 und Raster, aber ich kann einfach nicht scheinen, um herauszufinden, wie dies zu tun. Eines der Probleme, auf die ich gestoßen bin, ist, wie man ggplot2 zwischen 5m Tiefentemperaturmessung an Station 1 und 5m Temperaturmessung an Station 5 unterscheidet, da sie denselben Tiefenwert haben.

Auch wenn Sie mich zu einem anderen Programm führen können, die erlauben würden, mir einen Graphen wie diese zu erstellen, das wäre toll

+0

Dies ist wahrscheinlich auf Stack-Überlauf gehört –

Antwort

4

[REVISION]
(Bitte mir einen Kommentar, wenn Sie mehr geeignete Interpolationsverfahren wissen, schon gar nicht, um unter Bodendaten zu schneiden.)

ggplot() Bedürfnisse lange Datenform.

library(ggplot2) 

# example data 
max.depths <- c(1.1, 4, 4.7, 7.7, 8.2, 7.8, 10.7, 12.1, 14.3) 
depth.list <- sapply(max.depths, function(x) seq(0, x, 0.2)) 
temp.list <- list() 
set.seed(1); for(i in 1:9) temp.list[[i]] <- sapply(depth.list[[i]], function(x) rnorm(1, 20 - x*0.5, 0.2)) 
set.seed(1); dist <- c(0, sapply(seq(5, 40, 5), function(x) rnorm(1, x, 1))) 
dist.list <- sapply(1:9, function(x) rep(dist[x], length(depth.list[[x]]))) 

main.df <- data.frame(dist = unlist(dist.list), depth = unlist(depth.list) * -1, temp = unlist(temp.list)) 

# a raw graph 
ggplot(main.df, aes(x = dist, y = depth, z = temp)) + 
    geom_point(aes(colour = temp), size = 1) + 
    scale_colour_gradientn(colours = topo.colors(10)) 

# a relatively raw graph (don't run with this example data) 
ggplot(main.df, aes(x = dist, y = depth, z = temp)) + 
    geom_raster(aes(fill = temp)) + # geom_contour() + 
    scale_fill_gradientn(colours = topo.colors(10)) 

Wenn Sie ein Diagramm wie Sie möchten, müssen Sie eine Interpolation durchführen. Einige Pakete geben Ihnen räumliche Interpolationsmethoden. In diesem Beispiel habe ich akima Paket verwendet, aber Sie sollten ernsthaft denken, welche Interpolationsmethoden zu verwenden.

benutzte ich nx = 300 und ny = 300 in Code unten, aber ich denke, es wäre besser, diese Werte sorgfältig zu entscheiden. Large nx und ergibt eine hohe Auflösung Grafik, aber nicht real nx und (in diesem Beispiel ist real nx ist nur 9 und ist 101).

library(akima); library(dplyr) 

interp.data <- interp(main.df$dist, main.df$depth, main.df$temp, nx = 300, ny = 300) 
interp.df <- interp.data %>% interp2xyz() %>% as.data.frame() 
names(interp.df) <- c("dist", "depth", "temp") 

# draw interp.df 
ggplot(interp.df, aes(x = dist, y = depth, z = temp)) + 
    geom_raster(aes(fill = temp)) + # geom_contour() + 
    scale_fill_gradientn(colours = topo.colors(10)) 

# to think appropriateness of interpolation (raw and interpolation data) 
ggplot(interp.df, aes(x = dist, y = depth, z = temp)) + 
    geom_raster(aes(fill = temp), alpha = 0.3) +     # interpolation 
    scale_fill_gradientn(colours = topo.colors(10)) + 
    geom_point(data = main.df, aes(colour = temp), size = 1) + # raw 
    scale_colour_gradientn(colours = topo.colors(10)) 

enter image description here

Bottoms passen nicht !!
Ich fand ?interp sagt "Interpolation nur in konvexen Rumpf!", Oops ... Ich bin besorgt über die Interpolation um den Problembereich, ist es in Ordnung? Wenn kein Problem, müssen Sie nur die Daten unter den Böden schneiden. Wenn nicht, ... kann ich nicht sofort antworten (unten ist ein Beispielcode zu schneiden).

bottoms <- max.depths * -1 

# calculate bottom values using linear interpolation 
approx.bottoms <- approx(dist, bottoms, n = 300) # n must be the same value as interp()'s nx 

# change temp values under bottom into NA 
library(dplyr) 
interp.cut.df <- interp.df %>% cbind(bottoms = approx.bottoms$y) %>% 
    mutate(temp = ifelse(depth >= bottoms, temp, NA)) %>% select(-bottoms) 

ggplot(interp.cut.df, aes(x = dist, y = depth, z = temp)) + 
    geom_raster(aes(fill = temp)) + 
    scale_fill_gradientn(colours = topo.colors(10)) + 
    geom_point(data = main.df, size = 1) 

enter image description here

Wenn Sie stat_contour
Es ist schwieriger zu verwenden stat_contour als geom_raster verwenden möchten, weil es eine regelmäßige Gitterform benötigt. Soweit ich Ihren Graphen sehe, bilden Ihre Daten (Tiefe und Entfernung) kein regelmäßiges Raster, das heißt, es ist sehr schwierig, stat_contour mit Ihren Rohdaten zu verwenden. Also habe ich interp.cut.df verwendet, um ein Konturdiagramm zu zeichnen. Und stat_contour haben ein endemisches Problem (siehe How to fill in the contour fully using stat_contour), also müssen Sie Ihre Daten erweitern.

library(dplyr) 

# 1st: change NA into a temp's out range value (I used 0) 
interp.contour.df <- interp.cut.df 
interp.contour.df[is.na(interp.contour.df)] <- 0 

# 2nd: expand the df (It's a little complex, so please use this function) 
contour.support.func <- function(df) { 
    colname <- names(df) 
    names(df) <- c("x", "y", "z") 
    Range <- as.data.frame(sapply(df, range)) 
    Dim <- as.data.frame(t(sapply(df, function(x) length(unique(x))))) 
    arb_z = Range$z[1] - diff(Range$z)/20 
    df2 <- rbind(df, 
       expand.grid(x = c(Range$x[1] - diff(Range$x)/20, Range$x[2] + diff(Range$x)/20), 
          y = seq(Range$y[1], Range$y[2], length = Dim$y), z = arb_z), 
       expand.grid(x = seq(Range$x[1], Range$x[2], length = Dim$x), 
          y = c(Range$y[1] - diff(Range$y)/20, Range$y[2] + diff(Range$y)/20), z = arb_z)) 
names(df2) <- colname 
return(df2) 
} 

interp.contour.df2 <- contour.support.func(interp.contour.df) 
# 3rd: check the temp range (these values are used to define contour's border (breaks)) 
range(interp.cut.df$temp, na.rm=T)  # 12.51622 20.18904 

# 4th: draw ... the bottom border is dirty !! 
ggplot(interp.contour.df2, aes(x = dist, y = depth, z = temp)) + 
    stat_contour(geom="polygon", breaks = seq(12.51622, 20.18904, length = 11), aes(fill = ..level..)) + 
    coord_cartesian(xlim = range(dist), ylim = range(bottoms), expand = F) + # cut expanded area 
    scale_fill_gradientn(colours = topo.colors(10)) # breaks's length is 11, so 10 colors are needed 

# [Note] 
# You can define the contour's border values (breaks) and colors. 
contour.breaks <- c(12.5, 13.5, 14.5, 15.5, 16.5, 17.5, 18.5, 19.5, 20.5) 
    # = seq(12.5, 20.5, 1) or seq(12.5, 20.5, length = 9) 
contour.colors <- c("darkblue", "cyan3", "cyan1", "green3", "green", "yellow2","pink", "darkred") 
    # breaks's length is 9, so 8 colors are needed. 

# 5th: vanish the bottom border by bottom line 
approx.df <- data.frame(dist = approx.bottoms$x, depth = approx.bottoms$y, temp = 0) # 0 is dummy value 

ggplot(interp.contour.df2, aes(x = dist, y = depth, z = temp)) + 
    stat_contour(geom="polygon", breaks = contour.breaks, aes(fill = ..level..)) + 
    coord_cartesian(xlim=range(dist), ylim=range(bottoms), expand = F) + 
    scale_fill_gradientn(colours = contour.colors) + 
    geom_line(data = approx.df, lwd=1.5, color="gray50") 

enter image description here

Bonus: Legende technic
library(dplyr) 
interp.contour.df3 <- interp.contour.df2 %>% mutate(temp2 = cut(temp, breaks = contour.breaks)) 
interp.contour.df3$temp2 <- factor(interp.contour.df3$temp2, levels = rev(levels(interp.contour.df3$temp2))) 

ggplot(interp.contour.df3, aes(x = dist, y = depth, z = temp)) + 
    stat_contour(geom="polygon", breaks = contour.breaks, aes(fill = ..level..)) + 
    coord_cartesian(xlim=range(dist), ylim=range(bottoms), expand = F) + 
    scale_fill_gradientn(colours = contour.colors, guide = F) + # add guide = F 
    geom_line(data = approx.df, lwd=1.5, color="gray50") + 
    geom_point(aes(colour = temp2), pch = 15, alpha = 0) +  # add 
    guides(colour = guide_legend(override.aes = list(colour = rev(contour.colors), alpha = 1, cex = 5))) + # add 
    labs(colour = "temp") # add 

enter image description here

+0

Da ich nicht auf meinem Konto, da es veröffentlichen können war ein Temp orary one (Ich bin der OP), ich wollte Ihnen nur Tintenfisch44 danken. Ihre Antwort hat mir sehr geholfen. Ich habe jedoch eine Frage, die Funktion%>% wird von meiner Version von R mit der Interpolation nicht erkannt. Geht es um ein bestimmtes Paket oder könnten Sie mir die Funktion und eine Alternative erklären? Ich habe keinen Hintergrund. Danke nochmal :) T.Valz –

+0

@ T.Valz; Es ist eine 'Bibliothek (dplyr) 's Funktion. 'test <- 1:10 %>% matrix (nrow = 2)%>% as.data.frame()' bedeutet '1:10 -> temp',' matrix (temp, nrow = 2) -> temp2', 'as.data. Rahmen (temp2) -> test'. – cuttlefish44

+0

@ T.Valz; Tut mir leid, ich habe 'Bibliothek (akima)' unterschätzt. Sie können eine enorme Anzahl von Schritten speichern. Ich habe bearbeitet, bitte, bitte überprüfen Sie es. – cuttlefish44

2

Sie wollen, dass diese mit der Temperatur als z Dimension als 3-D-Oberfläche behandeln. Das gegebene Diagramm ist ein Konturdiagramm und es sieht so aus, als ob ggplot2 das mit stat_contour machen könnte.

Ich bin nicht sicher, wie die Konturlinien berechnet werden (oft ist es lineare Interpolation entlang einer Delaunay-Triangulation). Wenn Sie mehr Kontrolle darüber haben möchten, wie Sie zwischen Ihren x/y-Gitterpunkten interpolieren, können Sie zuerst ein Oberflächenmodell berechnen und diese z-Koordinaten in ggplot2 einspeisen.