2016-09-28 4 views
1

Мне нужно рассчитать глубину изотермы 25 градусов от данных HYCOM, которая имеет температуру 33 глубины океана в выбранной области.R: получить определенную глубину из многомерной матрицы уровней глубины

загрузить данные из NetCDF инструмента подмножества, используя ссылку ниже

http://ncss.hycom.org/thredds/ncss/GLBa0.08/latest/temp?var=temperature&north=25&west=74.1199&east=434.1199&south=-15&horizStride=1&time_start=2016-09-27T00%3A00%3A00Z&time_end=2016-09-27T23%3A59%3A00Z&timeStride=1&vertCoord=&accept=netcdf4 

набора данных в формате NetCDF 4 и импортированные, чтобы R от ncdf4 библиотеки

library(ncdf4) 
ncdata <- nc_open(file) 
lon <- ncvar_get(ncdata, "Longitude") 
lat <- ncvar_get(ncdata, "Latitude") 
temp <-ncvar_get(ncdata,"temperature") 
str(temp) 

Num [1: 4500, 1: 512, 1:33] 24.7 24.6 24.6 24.7 24.7 ...

Как найти глубину определенной температуры (25) из массива выше? Затем подставьте ее в небольшую область?

+0

Попытка иметь внешний вид, но не может получить доступ к файлу и данные для проверки. Было бы лучше, если бы вы опубликовали рабочую ссылку или подмножество переменной temp. – lbusett

+0

вы можете запустить 'apply' над массивом с функцией для поиска глубины - при простейшем' apply (temp, c (1, 2), finddepth) 'где finddepth - это функция, которая найдет глубину первого значения ниже 25 в один профиль глубины –

+0

@ Ссылка Lorenzo обновляется сейчас. – sudheera

ответ

0

Расширение на @Richard Telford отвечает, вам просто нужно применить функцию для z-размерности всех пикселей, которая вычисляет глубину, при которой температура пересекает 25 градусов. порог.

Очень просто, вы могли бы сделать:

file <- "http://ncss.hycom.org/thredds/ncss/GLBa0.08/latest/temp?var=temperature&north=25&west=74.1199&east=434.1199&south=-15&horizStride=1&time_start=2016-09-27T00%3A00%3A00Z&time_end=2016-09-27T23%3A59%3A00Z&timeStride=1&vertCoord=&accept=netcdf4" 
savefile = tempfile(, fileext = "nc4") 
download.file(file, savefile) 
library(ncdf4) 
ncdata <- nc_open(savefile) 
lon <- ncvar_get(ncdata, "Longitude") 
lat <- ncvar_get(ncdata, "Latitude") 
temp <-ncvar_get(ncdata,"temperature") 

temp <- temp [,,1:10] # subset depths to speed up 
depths <- 1:10 # let's define some dummy depths - you want to put actual values, here ! 

finddepth = function(pixtemp, ...) { 
    if (max(pixtemp, na.rm = TRUE) < predtemp$temp) { 
    NA # set to NA if no values >= 25 
    } else { 
    depth <- tryCatch({ 
     depth <- approx(pixtemp, depths,predtemp$temp)$y # interpolate using linear (faster) 
     # interp <- loess(depths~pixtemp) # interpolate using loess (slower - deals with non-linearity) 
     # depth <- predict(interp, predtemp$temp) # find depth @ temperature 
     return(depth) # send back computed depth 
    }, error = function(e) {NA} 
    ) 

    } 
} 
predtemp <- data.frame(temp = 25) # set desired isotherm 
iso_depth <- apply(temp, c(1, 2), FUN = finddepth) 

, который (я думаю) дает необходимые данные в "iso_depth":

library(lattice) 
levelplot(iso_depth, main = "Isotherm depth", col.regions = terrain.colors(250)) 

enter image description here

(В изображении , белые области соответствуют точке @, которая изотермы 25 ° не существует, поскольку максимальная температура равна < 25 °).

Здесь я использую линейную интерполяцию через «приблизительную», чтобы найти глубину @, которая имеет прямую линию между последней глубиной, на которой T> 25 и первая @, которые T < 25 пересекают уровень T = 25. Если линейная интерполяция не подходит для вас, вы можете раскомментировать две строки после «глубины < - approx (...)», и вы будете работать с локальной квадратичной интерполяцией лёсса (которая, однако, медленнее и дает больше NA).

Обратите внимание, что для того, чтобы иметь «значащие» значения, вам придется подставить переменную «глубина», которую я установил с правильными значениями глубины.

. Также обратите внимание, что это довольно медленно: более сложные подходы могут дать большую скорость. Вы можете получить большую скорость, выполнив параллельную обработку.

@sudheera предыдущие итерации терпели крах, потому что есть некоторые пиксели с 3 значениями не NA, а конструкция try catch имела ошибку.

НТН

Lorenzo

+0

Функция finddepth была применена к реальному набору данных. Но это дает ошибки.Ошибка в predLoess (y, x, newx, s, weight, pars $ roust, pars $ span, pars $ degree,: NA/NaN/Inf в вызове внешней функции (arg 5) Кроме того: было 50 или более предупреждения (используйте предупреждения(), чтобы увидеть первые 50) – sudheera

+0

Глубины не равны. глубины [1] 0 10 20 30 50 75 100 125 150 200 250 300 400 500 600 700 800 900 1000 [20] 1100 1200 1300 1400 1500 1750 2000 2500 3000 3500 4000 4500 5000 5500. Поскольку температура менее 24 градусов не может быть ниже 200 м, можно исключить глубину ниже 200 м от массива до применения функции? – sudheera

+0

относительно «исключая глубины», вы можете легко сделать это, подмножество температуры массив (например, 'temp <- temp [,, 1: 10]') или используя возможности подмножества 'ncvar_get' (см. справку - это избавит вас от некоторой памяти/времени). – lbusett