Saltar al contenido

Cómo interpolar datos entre puntos dispersos para hacer un gráfico de contorno en R & plotly

Tenemos la mejor información que encontramos en línea. Nosotros queremos que te sirva de ayuda y si quieres compartir cualquier detalle que nos pueda ayudar a perfeccionar nuestra información hazlo con total libertad.

Solución:

Primero que nada debes considerar que con + -30 puntos no es suficiente para conseguir esas limpias capas separadas que puedes ver en el ejemplo. Dicho eso, pongámonos a trabajar:

Primero, puede supervisar sus datos para adivinar cómo será la forma de esas capas. Aquí puede ver fácilmente que los valores z más bajos tienen valores de CO2 más altos.

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

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

ingrese la descripción de la imagen aquí

Una cosa importante es que tienes que definir las capas que vas a tener. Estas capas deben estar hechas a partir de la interpolación de valores en toda una superficie. Entonces:

  • Defina los datos que está utilizando para cada capa.
  • Interpolar los valores de zy de calCO2. Esto es importante porque se trata de dos cosas diferentes. La interpolación z hará el color del gráfico y el calCO2 hará el color (concentración o lo que sea). En su imagen de (https://plot.ly/r/3d-surface-plots/) el color yz representan lo mismo, mientras que aquí, supongo que desea representar la superficie de zy colorearla con calCO2. Es por eso que necesitará interpolar valores para ambos. Los métodos de interpolación son un mundo, aquí acabo de hacer una interpolación simple y he llenado NA con valores medios.

Aquí está el código:

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

ingrese la descripción de la imagen aquí

Como señala Cesar, debe definir las “capas” que desea interpolar en este sistema 3D.

Aquí, presento un enfoque asumiendo una capa (es decir, utilizo todos los puntos a lo largo de la dirección z). Mirar una tabla de sus valores le ayudará a definir dónde ocurren las rupturas. Puede reutilizar el código siguiente para cada “capa” que defina.

> table(d$z)

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

Ya que está tratando con datos espaciales, usemos objetos espaciales en R para resolver este problema.

Primero, copio / pego sus datos en una variable llamada 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) 

ingrese la descripción de la imagen aquí

Puede imaginar dividir sus datos en capas según la z valor del punto y volver a ejecutar este código para generar una interpolación para cada capa. Asegúrese de leer varios métodos de interpolación para determinar cuál es el más adecuado para su sistema. Una vez que tenga estas capas, no es mucho más trabajo transferir esos datos a ploty como se muestra arriba.


EDITAR: tomando base -> ggplot -> plotly es sencillo:

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

Aquí hay algunas instrucciones sobre cómo agregar etiquetas de contorno.

ingrese la descripción de la imagen aquí

Convierta esto en un objeto gráfico interactivo.

library(plotly)
ggplotly(p)

Y el código de la primera publicación te lleva a 3d.

Te mostramos las comentarios y valoraciones de los lectores

Si estás contento con lo expuesto, tienes la habilidad dejar un ensayo acerca de qué le añadirías a esta sección.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *