Почему обработанный файл NetCDF в среде R создает растры с другим разрешением по сравнению с созданными в ArcGIS?

#r #arrays #gis #netcdf4

#r #массивы #гис #netcdf4

Вопрос:

Я имею дело с файлом netcdf4, загруженным из службы мониторинга морской среды Copernicus, и мне кажется, я что-то здесь упускаю…

Рассмотрите мой подход в следующем коде для извлечения значений из файла nc. Моя задача — повторно проанализировать данные, хранящиеся во временных рядах, с помощью линейной регрессии, чтобы получить среднее изменение SST в день на пиксель (не совсем уверен, получаю ли я статистику, которую я хочу здесь! Я открыт для предложений! в любом случае, это не тема моей темы).

 library(ncdf4)
library(raster)
nc_data <- nc_open('L4_analyzed_sst_005res_25081981_31122018.nc')
print(nc_data) #it shows metadata

lon <- ncvar_get(nc_data, "lon")
lat <- ncvar_get(nc_data, "lat", verbose = F)
t <- ncvar_get(nc_data, "time")
t1 <- as.POSIXct(t, origin="1981-01-01", format="%Y-%m-%d", tz = "UTC")

sst.array <- ncvar_get(nc_data, "analysed_sst") # store the data in a 3-dimensional array (long, lat, time)
dim(sst.array)

fillvalue <- ncatt_get(nc_data, "analysed_sst", "_FillValue")
fillvalue
nc_close(nc_data)

sst.array[sst.array == fillvalue$value] <- NA #fill the no value with NA

str(sst.array)

##################################################################################################
#1. sst change for the entire period
#######################################################################################
slope_matrix <- matrix(nrow = length(lon), ncol = length(lat))
for (i in 1:dim(sst.array)[1]){
  for (j in 1:dim(sst.array)[2]){
    value <- sst.array[i,j,]
    if (anyNA(value)==FALSE){ #this "if" speed up the process because in my case the only NA are noValue
    extracted_data <- data.frame(value=value, t=t1)
    extracted_data$quarter <- "null"
    extracted_data$quarter <- ifelse(substr(extracted_data$t, 6,7)=="01"|substr(extracted_data$t, 6,7)=="02"|substr(extracted_data$t, 6,7)=="03", "Q1", extracted_data$quarter)
    extracted_data$quarter <- ifelse(substr(extracted_data$t, 6,7)=="04"|substr(extracted_data$t, 6,7)=="05"|substr(extracted_data$t, 6,7)=="06", "Q2", extracted_data$quarter)
    extracted_data$quarter <- ifelse(substr(extracted_data$t, 6,7)=="07"|substr(extracted_data$t, 6,7)=="08"|substr(extracted_data$t, 6,7)=="09", "Q3", extracted_data$quarter)
    extracted_data$quarter <- ifelse(substr(extracted_data$t, 6,7)=="10"|substr(extracted_data$t, 6,7)=="11"|substr(extracted_data$t, 6,7)=="12", "Q4", extracted_data$quarter)
    model <- lm(value ~ time(t)   quarter, data = extracted_data)
    slope_matrix[i,j] <- mean(predict(model) - extracted_data$value)
    }
  }
}

slope_raster <- raster(t(slope_matrix), xmn=min(lon), xmx=max(lon), ymn=min(lat), ymx=max(lat), crs=CRS(" proj=longlat  ellps=WGS84  datum=WGS84  no_defs  towgs84=0,0,0"))
plot(slope_raster)
slope_raster <- flip(slope_raster, direction='y')
writeRaster(slope_raster, "sst_change_1981-2018.tif", "GTiff", overwrite=TRUE)
  

Я использовал файл nc в качестве массива и построил вложенный цикл for для моделирования временных рядов в каждом пикселе. Затем я преобразовал матрицу значений в растр, перевернул его, чтобы переориентировать, и записал его как GeoTIFF для дальнейшего использования.
Теперь, когда я открываю его в ArcGIS, он не полностью перекрывается с растром, созданным с помощью инструмента «создать растровый слой NetCDF». Растр, созданный в R, имеет немного меньшее разрешение (0,049 против 0,050).

Вы знаете, в чем здесь проблема?

Спасибо за помощь!

РЕДАКТИРОВАТЬ: здесь вы можете загрузить данные.

Комментарии:

1. не могли бы вы, пожалуйста, переписать свой вопрос, чтобы сосредоточиться на рассматриваемой проблеме. Похоже, это правильное разрешение. Если да, то большая часть того, что вы показываете, не имеет значения, но вы не показываете многого, что может помочь ответить на ваш вопрос, так как мы можем знать. Можете ли вы сделать файл доступным? Можете показать raster::brick("file.nc") ?

2. Привет, Роберт. Я просто хотел показать, как я создал свой растр. Если процесс правильный, то я хотел бы знать, почему R и ArcGIS создают растры с разными разрешениями, вот и все. Я добавил ссылку на данные в вопросе.

3. Можете ли вы показать, что вы получаете с brick("file.nc") помощью и что вы получаете с помощью своего метода, чтобы мы могли сравнить (и удалить ненужные биты)?

Ответ №1:

Существуют гораздо более простые способы обработки файлов ncdf с пространственными данными. Ниже я открываю файл с raster пакетом (который имеет код на основе R для этого) и с terra пакетом (который использует библиотеку GDAL). Они дают одинаковое разрешение; поэтому можно с уверенностью предположить, что это правильно.

 f <- "L4_analyzed_sst_005res_25081981_31122018.nc"
library(raster)
b <- brick(f)
b
#class      : RasterBrick 
#dimensions : 34, 48, 1632, 13643  (nrow, ncol, ncell, nlayers)
#resolution : 0.05004599, 0.05015772  (x, y)
#extent     : 13.22879, 15.631, 39.52957, 41.23494  (xmin, xmax, ymin, ymax)
#crs        :  proj=longlat  datum=WGS84  no_defs 
#source     : L4_analyzed_sst_005res_25081981_31122018.nc 
#names      : X1981.08.25, X1981.08.26, X1981.08.27, X1981.08.28, X1981.08.29, X1981.08.30, X1981.08.31, X1981.09.01, X1981.09.02, X1981.09.03, X1981.09.04, X1981.09.05, X1981.09.06, X1981.09.07, X1981.09.08, ... 
#Date/time  : 1981-08-25, 2018-12-31 (min, max)
#varname    : analysed_sst 
  

Или с terra

 x <- rast(f)
x
#class       : SpatRaster 
#dimensions  : 34, 48, 13643  (nrow, ncol, nlyr)
#resolution  : 0.05004599, 0.05015772  (x, y)
#extent      : 13.22879, 15.631, 39.52957, 41.23494  (xmin, xmax, ymin, ymax)
#coord. ref. :  proj=longlat  datum=WGS84  no_defs 
#data source : L4_analyzed_sst_005res_25081981_31122018.nc 
#names       : L4__1, L4__2, L4__3, L4__4, L4__5, L4__6, ... 
 
  

Используемое вами разрешение неверно, потому что вы:

 raster(nrow=34, ncol=48, xmn=min(lon), xmx=max(lon), ymn=min(lat), ymx=max(lat))
#class      : RasterLayer 
#dimensions : 34, 48, 1632  (nrow, ncol, ncell)
#resolution : 0.04900336, 0.04868249  (x, y)
#extent     : 13.25381, 15.60598, 39.55465, 41.20986  (xmin, xmax, ymin, ymax)
#crs        :  proj=longlat  datum=WGS84  no_defs 
  

Вы используете значения lon / lat для центров угловых ячеек. Но что вам нужно указать, так это координаты внешнего края угловых ячеек.

Не имеет отношения к вашему вопросу, но теперь вы можете продолжить и вычислить кварталы (вне любого цикла — нет необходимости делать это снова и снова для каждой ячейки?)

 z <- getZ(b)
month <- as.numeric(substr(z, 6 ,7 ))
quarter <- ((month-1) %% 4 )   1
# or quarter <- trunc((month-1) / 3)   1
table(quarter)
#quarter
#   1    2    3    4 
#3434 3333 3435 3441 
  

И смотрите ?calc Примеры выполнения регрессии на основе ячеек

Комментарии:

1. Предположим, я использовал бы brick команду для доступа к файлу nc, как я мог бы достичь цели выполнения регрессионного анализа nlayers(b) для каждого ncell(b) и записать его как GeoTIFF ?

2. смотрите ?calc Примеры выполнения регрессии на основе ячеек — но вы также можете сохранить имеющийся у вас код регрессии и получить значения с помощью чего-то вроде values(b) , а затем установить значения с помощью setValues(raster(b), slope)

3. Большое вам спасибо, Роберт! Я все исправил с values помощью и setValues !!