Interpolation spatio-temporelle dans R ou ArcGIS?


12

J'essaie de calculer la valeur moyenne des précipitations à partir d'un certain nombre de points à l'aide de l'outil Inverse Weighted Distance dans ArcGIS 9.3.

Mon problème est que: chaque point a sa propre série temporelle, donc le processus d'interpolation devrait pouvoir se dérouler pour toutes les années (sorte d'itération pour ainsi dire).

Voici un exemple de table d'attributs:

ID X Y Name Rain1990 Rain1991 Rain1992 Rain1993 .... Rain2010

1 xx1 yy1 AA 1210 1189 1863 1269 ......  
2 xx2 yy2 BB 1492 1502 2187 1923 ......
......

Quelqu'un pourrait-il me montrer comment faire cela?


Edit 1: J'ai finalement fait cela en utilisant du code C ++ qui nécessitait la grille de masque ArcGIS, les fichiers de données et les emplacements de tous les points.


Edit 2: J'ai récemment utilisé R pour effectuer cette tâche d'interpolation. Vous pouvez utiliser soit hydroTSM, gstatsoit des spacetimepackages. Quelques exemples de liens ci-dessous:

http://spatial-analyst.net/wiki/index.php?title=Spatial_interpolation_exercises_%28NL%29

http://www.geostat-course.org/Topic_Bivand_2012


Edit 3: Ajout d'un exemple de travail ci-dessous pour les futurs lecteurs


Est-ce que cela vous aidera? Séries chronologiques
Brad Nesom

Cela pourrait être fait dans R, mais j'imagine qu'il existe un moyen simple de le faire directement dans ArcMap. Tout ce que le PO souhaite, c'est parcourir les variables distinctes (années) et calculer le raster interpolé pour chaque variable distincte. Le fait que les valeurs dans cet exemple soient des années séquentielles ne fait aucune différence.
Andy W

Merci pour votre réponse. En fait, il y a une option de lot lorsque vous cliquez avec le bouton droit sur l'outil IDW, mais c'est toujours un travail assez fastidieux si vous avez des données horaires ou quotidiennes. KR
Tung

@thecatalyst - Si l'outil batch IDW fait le travail, vous devez le poster comme réponse. Bien que cela puisse être fastidieux, s'il est peu fréquent (comme les estimations des précipitations annuelles sont peu fréquentes), alors il y a peu de raisons de chercher d'autres solutions.
Andy W

@Andy: L'outil batch aiderait si vous avez un nombre limité mais j'ai des centaines de données qui rendent l'idée de l'utiliser un peu irréaliste. Je cherche toujours la solution de ce problème. KR
Tung

Réponses:


3

J'ai résolu ce problème en insérant un itérateur "Sélection de fonctionnalités" dans un modèle. (Dans la fenêtre ModelBuilder, sous le menu Insertion-> Itérateurs.)

Utilisez votre champ de temps comme variable "regrouper par". Ce faisant, le modèle réitère une fois pour chaque fois dans votre classe d'entités.

Ensuite, attachez votre outil d'interpolation préféré (spline, IDW, peu importe) à la sortie d'entité de l'itérateur. Exécutez le modèle, partez en vacances pendant quelques semaines, et lorsque vous reviendrez, vous aurez autant de grilles que de points dans la classe d'entités.

Notez que cette solution suppose que vous avez des points d'échantillonnage temporels discrets avec une date ou un champ numérique qui indique un point temporel unique pour chaque enregistrement de votre ensemble de fonctionnalités. Si vous utilisez le format "heure de début" et "heure de fin", ce n'est peut-être pas si simple.


1
N'oubliez pas non plus d'utiliser la variable "% n%" dans le nom de votre fichier de sortie (ou une autre manière de générer un nom de fichier unique), sinon vous pouvez écraser votre raster à chaque itération. Pour plus d'informations, voir help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//… ou simplement google "Exemples de substitution de variables en ligne avec des variables système ModelBuilder"

TY. C'est bon de savoir qu'il existe une façon différente de procéder. À votre santé!
Tung

2

Il semble que ce thread soit répondu par l'outil IDW, mais si vous demandiez et saisissiez l'année de début, puis parcouriez les champs de l'année en utilisant une variable en ligne dans le générateur de modèles, ce serait une façon plus élégante de gérer la modélisation .

PS: Je suis d'accord avec @AndyW que si vous l'avez résolu en utilisant l'IDW, postez vous-même une réponse puis "marquez avec la coche"


1

Ajouter ma propre solution en utilisant Rdes données de précipitations aléatoires

library(tidyverse)
library(sp) # for coordinates, CRS, proj4string, etc
library(gstat)
library(maptools)

# Coordinates of gridded precipitation cells
precGridPts <- ("ID lat long
                1 46.78125 -121.46875
                2 46.84375 -121.53125
                3 46.84375 -121.46875
                4 46.84375 -121.40625
                5 46.84375 -121.34375
                6 46.90625 -121.53125
                7 46.90625 -121.46875
                8 46.90625 -121.40625
                9 46.90625 -121.34375
                10 46.90625 -121.28125
                11 46.96875 -121.46875
                12 46.96875 -121.40625
                13 46.96875 -121.34375
                14 46.96875 -121.28125
                15 46.96875 -121.21875
                16 46.96875 -121.15625
                ")

# Read precipitation cells
precGridPtsdf <- read.table(text = precGridPts, header = TRUE)

Convertir en objet sp

sp::coordinates(precGridPtsdf) <- ~long + lat # longitude first

Ajoutez un système de référence spatiale (SRS) ou un système de référence de coordonnées (CRS).

# CRS database: http://spatialreference.org/ref/epsg/
sp::proj4string(precGridPtsdf) <- sp::CRS("+proj=longlat +ellps=WGS84 +datum=WGS84")
str(precGridPtsdf)
#> Formal class 'SpatialPointsDataFrame' [package "sp"] with 5 slots
#>   ..@ data       :'data.frame':  16 obs. of  1 variable:
#>   .. ..$ ID: int [1:16] 1 2 3 4 5 6 7 8 9 10 ...
#>   ..@ coords.nrs : int [1:2] 3 2
#>   ..@ coords     : num [1:16, 1:2] -121 -122 -121 -121 -121 ...
#>   .. ..- attr(*, "dimnames")=List of 2
#>   .. .. ..$ : chr [1:16] "1" "2" "3" "4" ...
#>   .. .. ..$ : chr [1:2] "long" "lat"
#>   ..@ bbox       : num [1:2, 1:2] -121.5 46.8 -121.2 47
#>   .. ..- attr(*, "dimnames")=List of 2
#>   .. .. ..$ : chr [1:2] "long" "lat"
#>   .. .. ..$ : chr [1:2] "min" "max"
#>   ..@ proj4string:Formal class 'CRS' [package "sp"] with 1 slot
#>   .. .. ..@ projargs: chr "+proj=longlat +ellps=WGS84 +datum=WGS84 +towgs84=0,0,0"

Convertir en UTM 10N

utm10n <- "+proj=utm +zone=10 ellps=WGS84"
precGridPtsdf_UTM <- spTransform(precGridPtsdf, CRS(utm10n))

Données hypothétiques sur les précipitations annuelles générées à l'aide de la distribution de Poisson.

precDataTxt <- ("ID PRCP2016 PRCP2017 PRCP2018
                1 2125 2099 2203
                2 2075 2160 2119
                3 2170 2153 2180
                4 2130 2118 2153
                5 2170 2083 2179
                6 2109 2008 2107
                7 2109 2189 2093
                8 2058 2170 2067
                9 2154 2119 2139
                10 2056 2184 2120
                11 2080 2123 2107
                12 2110 2150 2175
                13 2176 2105 2126
                14 2088 2057 2199
                15 2032 2029 2100
                16 2133 2108 2006"
)

precData <- read_table2(precDataTxt, col_types = cols(ID = "i"))

Fusionner le bloc de données Prec avec le fichier de formes Prec

precGridPtsdf <- merge(precGridPtsdf, precData, by.x = "ID", by.y = "ID")
precdf <- data.frame(precGridPtsdf)

Fusionner la trame de données des précipitations avec le fichier de formes des précipitations (UTM)

precGridPtsdf_UTM <- merge(precGridPtsdf_UTM, precData, by.x = "ID", by.y = "ID")

# sample extent
region_extent <- structure(c(612566.169007975, 5185395.70942594, 639349.654465079, 
                             5205871.0782451), .Dim = c(2L, 2L), .Dimnames = list(c("x", "y"
                             ), c("min", "max")))

Définissez l'étendue de l'interpolation spatiale. Rendez-le 4 km plus grand dans chaque direction

x.range <- c(region_extent[1] - 4000, region_extent[3] + 4000)
y.range <- c(region_extent[2] - 4000, region_extent[4] + 4000)

Créez la grille souhaitée à une résolution de 1 km

grd <- expand.grid(x = seq(from = x.range[1], to = x.range[2], by = 1000), 
                   y = seq(from = y.range[1], to = y.range[2], by = 1000))   

# Convert grid to spatial object
coordinates(grd) <- ~x + y
# Use the same projection as boundary_UTM
proj4string(grd) <- "+proj=utm +zone=10 ellps=WGS84 +ellps=WGS84"
gridded(grd) <- TRUE

Interpoler en utilisant la distance inverse pondérée (IDW)

idw <- idw(formula = PRCP2016 ~ 1, locations = precGridPtsdf_UTM, newdata = grd)  
#> [inverse distance weighted interpolation]

# Clean up
idw.output = as.data.frame(idw)
names(idw.output)[1:3] <- c("Longitude", "Latitude", "Precipitation")

precdf_UTM <- data.frame(precGridPtsdf_UTM)

Résultats d'interpolation de tracé

idwPlt1 <- ggplot() + 
  geom_tile(data = idw.output, aes(x = Longitude, y = Latitude, fill = Precipitation)) +
  geom_point(data = precdf_UTM, aes(x = long, y = lat, size = PRCP2016), shape = 21, colour = "red") +
  viridis::scale_fill_viridis() + 
  scale_size_continuous(name = "") +
  theme_bw() +
  scale_x_continuous(expand = c(0, 0)) +
  scale_y_continuous(expand = c(0, 0)) +
  theme(axis.text.y = element_text(angle = 90)) +
  theme(axis.title.y = element_text(margin = margin(t = 0, r = 10, b = 0, l = 0))) 
idwPlt1

### Now looping through every year 
list.idw <- colnames(precData)[-1] %>% 
  set_names() %>% 
  map(., ~ idw(as.formula(paste(.x, "~ 1")), 
               locations = precGridPtsdf_UTM, newdata = grd)) 

#> [inverse distance weighted interpolation]
#> [inverse distance weighted interpolation]
#> [inverse distance weighted interpolation]

idw.output.df = as.data.frame(list.idw) %>% as.tibble()
idw.output.df

#> # A tibble: 1,015 x 12
#>    PRCP2016.x PRCP2016.y PRCP2016.var1.pred PRCP2016.var1.var PRCP2017.x
#>  *      <dbl>      <dbl>              <dbl>             <dbl>      <dbl>
#>  1    608566.   5181396.              2114.                NA    608566.
#>  2    609566.   5181396.              2115.                NA    609566.
#>  3    610566.   5181396.              2116.                NA    610566.
#>  4    611566.   5181396.              2117.                NA    611566.
#>  5    612566.   5181396.              2119.                NA    612566.
#>  6    613566.   5181396.              2121.                NA    613566.
#>  7    614566.   5181396.              2123.                NA    614566.
#>  8    615566.   5181396.              2124.                NA    615566.
#>  9    616566.   5181396.              2125.                NA    616566.
#> 10    617566.   5181396.              2125.                NA    617566.
#> # ... with 1,005 more rows, and 7 more variables: PRCP2017.y <dbl>,
#> #   PRCP2017.var1.pred <dbl>, PRCP2017.var1.var <dbl>, PRCP2018.x <dbl>,
#> #   PRCP2018.y <dbl>, PRCP2018.var1.pred <dbl>, PRCP2018.var1.var <dbl>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.