2016-09-25 66 views
3

我試圖用變量深度,距離和溫度創建深度剖面圖。收集的數據來自9個不同的點,它們之間有已知距離(距離5m,9個站,9組不同的數據)。溫度讀數是根據這9個測站,一個探測器直接下落,每2秒讀取一次溫度讀數。 9個站的每個站的最大深度也是從船上取下的。深度剖析可視化

所以我的數據是:

  1. 深度在各9個站(y軸)
  2. 溫度讀數在每一個9個站中的,在約0.2米間隔垂直直到底部是達到(填充區域)
  3. 在站之間的距離,(x軸)

是否有可能創造一個類似的深度分佈? (顯然沒有在這個圖中的更高分辨率)

enter image description here

我已經嘗試過用GGPLOT2和光柵亂搞,但我似乎無法弄清楚如何做到這一點。 我遇到的一個問題是如何讓ggplot2區別在站1的5米深度溫度讀數和站5的5米溫度讀數之間,因爲它們具有相同的深度值。

即使你能引導我走向另一個程序,讓我來創建這樣一個圖,這將是巨大

+0

這可能屬於對堆棧溢出 –

回答

4

[修訂]
(請評論我,如果你知道更多適合的插值方法,尤其是不需要在底部的數據削減。)

ggplot()需要較長的數據形式。

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

如果你想要一個像你這樣的圖表顯示,你必須做插值。一些軟件包爲您提供空間插值方法。在這個例子中,我使用了akima包但你應該認真認爲表示使用哪種插值方法。

我在下面的代碼中使用了nx = 300ny = 300,但我認爲最好是仔細確定這些值。大nxny給出高分辨率圖表,但不預測實際nxny(在此示例中,實際nx僅爲9且ny爲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

下裝不匹配!
我發現?interp說「只能在凸包內插值!」,哎呀......我對圍繞問題區域的插值很擔心,可以嗎?如果沒有問題,你只需要削減底部的數據。如果不是,我不能立即回答(下面是一個示例代碼)。

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

如果你想使用stat_contour
這是很難用stat_contourgeom_raster,因爲它需要規則的網格形式。就我看到你的圖形而言,你的數據(深度和距離)不會形成規則的網格,這意味着使用stat_contour與你的原始數據很難。所以我用interp.cut.df畫一個等高線圖。 stat_contour有一個地方性問題(見How to fill in the contour fully using stat_contour),所以你需要擴大你的數據。

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

獎金:傳說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

因爲我不能在我的帳戶後,因爲它是一個溫度(我是OP),我只是想感謝你墨魚44。你的答案幫了很大忙。我有一個問題,函數%>%沒有被我的版本R與插值識別。它是來自特定的軟件包還是可以向我解釋它的功能和替代方法?我真的沒有背景。再次感謝:) T.Valz –

+0

@ T.Valz;它是一個'library(dplyr)'的函數。 'test <- 1:10 %>%matrix(nrow = 2)%>%as.data.frame()'表示'1:10 - > temp','matrix(temp,nrow = 2) - > temp2','as.data。幀(temp2) - >測試「。 – cuttlefish44

+0

@ T.Valz;對不起,我低估了'庫(akima)'。您可以節省大量的步驟。我編輯過,請檢查一下。 – cuttlefish44

2

你要正確對待這個與溫度z方向的3 d面。給定的圖是一個等高線圖,看起來像ggplot2可以做到這一點與stat_contour

我不知道如何計算輪廓線(通常是沿Delaunay三角剖分的線性插值)。如果您想要更多地控制如何在x/y網格點之間進行插值,可以先計算曲面模型並將這些z座標輸入到ggplot2中。