简体   繁体   English

如何在稀疏点之间插入数据以在R&plot中绘制轮廓图

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

I'd like to create a contour plot on th xy plane from concentration data at the following coloured points in the fist figure. 我想根据第一张图中以下彩色点的浓度数据在xy平面上创建等高线图。 I don't have corner points at each height so I need to extrapolate the concentration to the edges of the xy plane (xlim=c(0,335),ylim=c(0,426)). 我在每个高度都没有角点,所以我需要将浓度外推到xy平面的边缘(xlim = c(0,335),ylim = c(0,426))。

在此输入图像描述 The plotly html file of the points is available here: https://leeds365-my.sharepoint.com/:u:/r/personal/cenmk_leeds_ac_uk/Documents/Documents/HECOIRA/Chamber%20CO2%20Experiments/Sensors.html?csf=1&e=HiX8fF 点的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)))

I'm trying to find something like this. 我想找到这样的东西。 Any help would be much appreciated. 任何帮助将非常感激。

在此输入图像描述

First of all you must consider that with +-30 points is not enough to get those clean separated layers that you can see in the example. 首先,您必须考虑使用+ -30点不足以获得您在示例中可以看到的那些干净的分离层。 Said that, lets get into work: 说,让我们开始工作:

First you can oversee your data in order to guess how is going to be the shape of those layers. 首先,您可以监督您的数据,以便猜测这些图层的形状。 Here you can easily see that lower z values have higher CO2 values. 在这里,您可以很容易地看到较低的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)

在此输入图像描述

An important thing is that you have to define the layers you are going to have. 重要的是你必须定义你将拥有的图层。 These layers must be made from interpolation of values all over a surface. 这些层必须通过整个表面上的值插值来制作。 So: 所以:

  • Define the data you are using for each layer. 定义您为每个图层使用的数据。
  • Interpolate values for z and for calCO2. 插值z和calCO2的值。 This is important because these are two different things. 这很重要,因为这是两件不同的事情。 z interpolation will make the sape of the graphic and calCO2 will make the color (concentration or whatever). z插值将使图形的sape和calCO2将产生颜色(浓度或其他)。 In your image from ( https://plot.ly/r/3d-surface-plots/ ) color and z are representing the same while here, I guess that you want to represent the surface of z and colored it with the calCO2. 在( https://plot.ly/r/3d-surface-plots/ )的图像中,颜色和z在这里表示相同,我想你想要表示z的表面并用calCO2着色它。 Thats why you will need to interpolate values for both. 这就是为什么你需要为两者插值。 Interpolation methods is a world, here I just did a simple interpolation and I've filled NA by mean values. 插值方法是一个世界,在这里我只做了一个简单的插值,我用平均值填充了NA。

Here is the code: 这是代码:

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

在此输入图像描述

As Cesar points out, you need to define the "layers" that you want to interpolate over in this 3d system. 正如Cesar指出的那样,您需要在此3d系统中定义要插入的“图层”。

Here, I present an approach assuming one layer (ie - I use all points along the z direction). 在这里,我提出了一种假设一层的方法(即 - 我使用沿z方向的所有点)。 Looking at a table of your values will help you to define where the breaks occur. 查看值的表将帮助您定义中断发生的位置。 You can re-use the code below for each "layer" you define. 您可以为您定义的每个“图层”重复使用以下代码。

> table(d$z)

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

Since you're dealing with spatial data, let's use spatial objects in R to solve this problem. 由于您正在处理空间数据,所以让我们使用R中的空间对象来解决这个问题。

First, I copy/pasted your data into a variable called d . 首先,我将您的数据复制/粘贴到名为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) 

在此输入图像描述

You can imagine splitting your data into layers based on the z value of the point, and re-running this code to generate an interpolation for each layer. 您可以想象基于点的z值将数据拆分为多个层,并重新运行此代码以为每个层生成插值。 Be sure to read up on various interpolation methods to determine which is best suited for your system. 请务必阅读各种插值方法,以确定哪种方法最适合您的系统。 Once you have these layers, it's not much more work to port that data into ploty like shown above. 一旦你有了这些图层,将这些数据移植到如上所示的ploty中就没那么多了。


EDIT: taking base --> ggplot --> plotly is straightforward: 编辑:采取基础 - > 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()

Here's some instructions on adding contour labels . 以下是添加轮廓标签的一些说明

在此输入图像描述

Turn this into an interactive plotly object. 把它变成一个交互式的情节对象。

library(plotly)
ggplotly(p)

And the code in the first post takes you to 3d. 第一篇文章中的代码将您带到3d。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM