簡體   English   中英

如何在稀疏點之間插入數據以在R&plot中繪制輪廓圖

[英]How to interpolate data between sparse points to make a contour plot in R & plotly

我想根據第一張圖中以下彩色點的濃度數據在xy平面上創建等高線圖。 我在每個高度都沒有角點,所以我需要將濃度外推到xy平面的邊緣(xlim = c(0,335),ylim = c(0,426))。

在此輸入圖像描述 點的html文件可以在這里找到: https ://leeds365-my.sharepoint.com/:u:/ r / personal /cenmk_leeds_ac_uk / Files / Files / HECOIRA /Chamber%20CO2%20Experiments/Sensors.html?csf = 1&E = HiX8fF

dput(df)
structure(list(Sensor = structure(c(11L, 12L, 13L, 14L, 15L, 
16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 
29L, 1L, 3L, 4L, 5L, 6L, 8L, 30L, 31L, 32L, 33L, 34L, 35L), .Label = c("N1", 
"N2", "N3", "N4", "N5", "N6", "N7", "N8", "N9", "Control", "A1", 
"A10", "A11", "A12", "A13", "A14", "A15", "A16", "A17", "A18", 
"A19", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "R1", 
"R2", "R3", "R4", "R5", "R6"), class = "factor"), calCO2 = c(2237, 
2389.5, 2226.5, 2321, 2101.5, 1830.5, 2418, 2356.5, 435, 2345.5, 
2376, 2451, 2397, 2466, 2518.5, 2087, 2463, 2256.5, 2345.5, 3506, 
2950, 3386, 2511, 2385, 3441, 2473, 2357.5, 2052.5, 2318, 1893.5, 
2251), x = c(83.75, 167.5, 167.5, 167.5, 251.25, 167.5, 251.25, 
251.25, 0, 83.75, 251.25, 167.5, 251.25, 83.75, 83.75, 83.75, 
83.75, 251.25, 167.5, 335, 0, 0, 335, 167.5, 167.5, 167.5, 0, 
335, 335, 167.5, 167.5), y = c(213, 319.5, 319.5, 110, 319.5, 
213, 110, 110, 356, 213, 319.5, 110, 213, 110, 319.5, 319.5, 
110, 213, 213, 0, 0, 426, 426, 426, 0, 213, 213, 70, 213, 426, 
0), z = c(155, 50, 155, 155, 155, 226, 50, 155, 178, 50, 50, 
50, 50, 155, 50, 155, 50, 155, 50, 0, 0, 0, 0, 0, 0, 0, 130, 
50, 120, 130, 130), Type = c("Airnode", "Airnode", "Airnode", 
"Airnode", "Airnode", "Airnode", "Airnode", "Airnode", "Airnode", 
"Airnode", "Airnode", "Airnode", "Airnode", "Airnode", "Airnode", 
"Airnode", "Airnode", "Airnode", "Airnode", "Naveed", "Naveed", 
"Naveed", "Naveed", "Naveed", "Naveed", "Rotronic", "Rotronic", 
"Rotronic", "Rotronic", "Rotronic", "Rotronic")), .Names = c("Sensor", 
"calCO2", "x", "y", "z", "Type"), row.names = c(NA, -31L), class = "data.frame")

require(plotly)

plot_ly(data = subset(df,z==0), x=~x,y=~y, z=~calCO2, type = "contour") %>%
  layout(
    xaxis = list(range = c(340, 0), autorange = F, autorange="reversed"), 
    yaxis = list(range = c(0, 430)))

我想找到這樣的東西。 任何幫助將非常感激。

在此輸入圖像描述

首先,您必須考慮使用+ -30點不足以獲得您在示例中可以看到的那些干凈的分離層。 說,讓我們開始工作:

首先,您可以監督您的數據,以便猜測這些圖層的形狀。 在這里,您可以很容易地看到較低的z值具有較高的CO2值。

require(dplyr)
require(plotly)
require(akima)
require(plotly)
require(zoo)
require(raster)

plot_ly(df, x=~x,y=~y, z=~z, color =~calCO2)

在此輸入圖像描述

重要的是你必須定義你將擁有的圖層。 這些層必須通過整個表面上的值插值來制作。 所以:

  • 定義您為每個圖層使用的數據。
  • 插值z和calCO2的值。 這很重要,因為這是兩件不同的事情。 z插值將使圖形的sape和calCO2將產生顏色(濃度或其他)。 在( https://plot.ly/r/3d-surface-plots/ )的圖像中,顏色和z在這里表示相同,我想你想要表示z的表面並用calCO2着色它。 這就是為什么你需要為兩者插值。 插值方法是一個世界,在這里我只做了一個簡單的插值,我用平均值填充了NA。

這是代碼:

## Define your layers in z range (by hand or use quantiles, percentiles, etc.)
df1 <- subset(df, z >= 0 & z <= 125) #layer between 0 and 150m
df2 <- subset(df, z > 125)           #layer between 150 and max

#interpolate values for each layer and for z and co2
z1 <- interp(df1$x, df1$y, df1$z, extrap = TRUE, duplicate = "mean") #interp z layer 1 with spline interp
ifelse(anyNA(z1$z) == TRUE, z1$z[is.na(z1$z)] <- mean(z1$z, na.rm = TRUE), NA) #fill na cells with mean value

z2 <- interp(df2$x, df2$y, df2$z, extrap = TRUE, duplicate = "mean") #interp z layer 2 with spline interp
ifelse(anyNA(z2$z) == TRUE, z2$z[is.na(z2$z)] <- mean(z2$z, na.rm = TRUE), NA) #fill na cells with mean value

c1 <- interp(df1$x, df1$y, df1$calCO2, extrap = F, linear = F, duplicate = "mean") #interp co2 layer 1 with spline interp
ifelse(anyNA(c1$z) == TRUE, c1$z[is.na(c1$z)] <- mean(c1$z, na.rm = TRUE), NA) #fill na cells with mean value

c2 <- interp(df2$x, df2$y, df2$calCO2, extrap = F, linear = F, duplicate = "mean") #interp co2 layer 2 with spline interp
ifelse(anyNA(c2$z) == TRUE, c2$z[is.na(c2$z)] <- mean(c2$z, na.rm = TRUE), NA) #fill na cells with mean value

#THE PLOT
p <- plot_ly(showscale = TRUE) %>%
    add_surface(x = z1$x, y = z1$y, z = z1$z, cmin = min(c1$z), cmax = max(c2$z), surfacecolor = c1$z) %>%
    add_surface(x = z2$x, y = z2$y, z = z2$z, cmin = min(c1$z), cmax = max(c2$z), surfacecolor = c2$z) %>%
    add_trace(data = df, x = ~x, y = ~y, z = ~z, mode = "markers", type = "scatter3d", 
              marker = list(size = 3.5, color = "red", symbol = 10))%>%
    layout(title="Stack Exchange Plot")
p

在此輸入圖像描述

正如Cesar指出的那樣,您需要在此3d系統中定義要插入的“圖層”。

在這里,我提出了一種假設一層的方法(即 - 我使用沿z方向的所有點)。 查看值的表將幫助您定義中斷發生的位置。 您可以為您定義的每個“圖層”重復使用以下代碼。

> table(d$z)

  0  50 120 130 155 178 226 
  7  10   1   3   8   1   1 

由於您正在處理空間數據,所以讓我們使用R中的空間對象來解決這個問題。

首先,我將您的數據復制/粘貼到名為d的變量中。

# make d into a SpatialPointsDataFrame object
library(sp)
coords <- d[, c("x", "y")]
s      <- SpatialPointsDataFrame(coords = coords, data = d)

# interpolate with a thin plate spline 
# (or another interpolation method: kriging, inverse distance weighting). 
library(raster)
library(fields)
tps <- Tps(coordinates(s), as.vector(d$calCO2))
p   <- raster(s)
p   <- interpolate(p, tps)

# plot raster, points, and contour lines
plot(p)
plot(s, add=T)
contour(p, add=T) 

在此輸入圖像描述

您可以想象基於點的z值將數據拆分為多個層,並重新運行此代碼以為每個層生成插值。 請務必閱讀各種插值方法,以確定哪種方法最適合您的系統。 一旦你有了這些圖層,將這些數據移植到如上所示的ploty中就沒那么多了。


編輯:采取基礎 - > ggplot - >情節簡單明了:

# ggplot
library(ggplot2)
p <- ggplot(as.data.frame(p, xy = TRUE), aes(x, y, fill = layer)) + 
  geom_tile() + 
  geom_contour(aes(z = layer), color = "white") + 
  scale_fill_viridis_c() + 
  theme_minimal()

以下是添加輪廓標簽的一些說明

在此輸入圖像描述

把它變成一個交互式的情節對象。

library(plotly)
ggplotly(p)

第一篇文章中的代碼將您帶到3d。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM