Почему пакет R netCDF4 транспонирует мои данные? - PullRequest
0 голосов
/ 31 марта 2020

Я читаю данные .n c в R с помощью ncdf4 и RNetCDF. Метаданные NetCDF говорят, что есть 144 лона и 73 лата, что приводит к 144 столбцам и 73 строкам, верно?

Однако данные, которые я получаю в R, похоже, транспонированы с 144 строками и 73 столбцами.

Скажите, пожалуйста, в чем дело?

спасибо

    library(ncdf4)
    a <- tempfile()
    download.file(url = "ftp://ftp.cdc.noaa.gov/Datasets/ncep.reanalysis2.derived/pressure/uwnd.mon.mean.nc", destfile = a)
    nc <- nc_open(a)
    print(nc)
    File uwnd.mon.mean.nc (NC_FORMAT_CLASSIC):

         2 variables (excluding dimension variables):
            double time_bnds[nbnds,time]   
                long_name: Time Boundaries
            short uwnd[lon,lat,level,time]   
                long_name: Monthly U-wind on Pressure Levels
                valid_range: -32765
                 valid_range: -1266
                unpacked_valid_range: -140
                 unpacked_valid_range: 175
                actual_range: -58.9100112915039
                 actual_range: 103.155143737793
                units: m/s
                add_offset: 187.649993896484
                scale_factor: 0.00999999977648258
                missing_value: 32766
                _FillValue: -32767
                precision: 2
                least_significant_digit: 1
                GRIB_id: 33
                GRIB_name: UGRD
                var_desc: u-wind
                dataset: NCEP/DOE AMIP-II Reanalysis (Reanalysis-2) Monthly Averages
                level_desc: Pressure Levels
                statistic: Individual Obs
                parent_stat: Other
                standard_name: eastward_wind
                cell_methods: time: mean (monthly from 6-hourly values)

         5 dimensions:
            lon  Size:144
                units: degrees_east
                long_name: Longitude
                actual_range: 0
                 actual_range: 357.5
                standard_name: longitude
                axis: X
                coordinate_defines: point
            lat  Size:73
                units: degrees_north
                actual_range: 90
                 actual_range: -90
                long_name: Latitude
                standard_name: latitude
                axis: Y
                coordinate_defines: point
            level  Size:17
                units: millibar
                actual_range: 1000
                 actual_range: 10
                long_name: Level
                positive: down
                GRIB_id: 100
                GRIB_name: hPa
                axis: Z
                coordinate_defines: point

    uwnd <- ncvar_get(nc = ncu, varid = "uwnd")
    dim(uwnd)
    [1] 144  73  17 494
    umed <- (uwnd[ , , 10, 421] + uwnd[ , , 10, 422] + uwnd[ , , 10, 423])/3
    nrow(umed)
    [1] 144
    ncol(umed)
    [1] 73

1 Ответ

0 голосов
/ 16 апреля 2020

Похоже, у вас две проблемы.

Первая связана с ожиданием той же структуры, что и файл netCDF в R, что является проблемой. само по себе, потому что, когда вы переводите многомерную структуру массива netCDF в двухмерный фрейм данных. Формат NetCDF нуждается в некотором изменении формы в R для того, чтобы манипулировать им, как в python (см .: http://geog.uoregon.edu/bartlein/courses/geog490/week04-netCDF.html).

Второй заключается в том, что вы используете значения вместо индексов при подборе данных.

umed <- (uwnd[ , , 10, 421] + uwnd[ , , 10, 422] + uwnd[ , , 10, 423])/3

Решение , которое я вижу для этого, начинается с создания индексов измерений, которые вы хотите поднастроить. В этом примере я устанавливаю уровень уверенности 10 миллибар и все, что идет между долготой 230 и 300 и широтой 25 и 40.

nc <- nc_open("uwnd.mon.mean.nc")

LonIdx <- which( nc$dim$lon$vals > 230 & nc$dim$lon$vals <300 )
## [1]  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111 112 113         
## 114 115 116 117 118 119 120
LatIdx <- which( nc$dim$lat$vals >25  & nc$dim$lat$vals < 40)
## [1] 22 23 24 25 26
LevIdx <- which( nc$dim$level$vals==10)
## [1] 17

Тогда вам нужно будет применять индексы для каждого измерения, кроме времени, которое я бы Предположим, вы не хотите подмножество. Подстановка lon и latitude важна, потому что R сохраняет все в памяти, поэтому оставление всего их диапазона потребует значительного объема оперативной памяти.

lat <- ncvar_get(nc,"lat")[LatIdx]
lon <- ncvar_get(nc,"lon")[LonIdx] 
lev <- ncvar_get(nc,"level")[LevIdx]
time <- ncvar_get(nc,"time")

После этого вы можете получить переменную, которую искали uwnd Ежемесячный U-ветер на уровнях давления и окончание sh чтение файла netCDF с помощью nc_close(nc).

uwnd <- ncvar_get(nc,"uwnd")[LonIdx,LatIdx,LevIdx,] 
nc_close(nc)

В конце вы можете расширить сетку всеми четырьмя измерения: долгота, широта, уровень уверенности и время.

uwndf <- data.frame(as.matrix(cbind(expand.grid(lon,lat,lev,time))),c(uwnd))
names(uwndf) <- c("lon","lat","level","time","U-wind")

Свяжите его с кадром данных с помощью переменной U-wind и преобразуйте переменную времени netcdf в объект времени R.

uwndf$time_final<-convertDateNcdf2R(uwndf$time, units = "hours", origin =          
as.POSIXct("1800-01-01",  tz = "UTC"),time.format="%Y-%m-%d %Z %H:%M:%S")

В конце у вас будет дата-кадр, который вы ищете в период с января 1979 года по март 2020 года.

max(uwndf$time_final)
## [1] "2020-03-01 UTC"
min(uwndf$time_final)
## [1] "1979-01-01 UTC"
head(uwndf)
##     lon  lat level    time    U-wind time_final
## 1 232.5 37.5    10 1569072  3.289998 1979-01-01
## 2 235.0 37.5    10 1569072  5.209998 1979-01-01
## 3 237.5 37.5    10 1569072  7.409998 1979-01-01
## 4 240.0 37.5    10 1569072  9.749998 1979-01-01
## 5 242.5 37.5    10 1569072 12.009998 1979-01-01
## 6 245.0 37.5    10 1569072 14.089998 1979-01-01

Надеюсь, это полезно! Приветствия!

Примечание. Для преобразования временной переменной netcdf в объект времени R убедитесь, что у вас установлена ​​библиотека ncdf.tools.

...