如何有效地将 NCDF 时间转换为适当的单位
How to effectively convert NCDF time into proper units
我正在尝试将 netCDF 文件中的时间单位转换为正确的格式,但是,我得到了错误的输出。
我使用的数据有时间格式:
1 dimensions:
time Size:193458 *** is unlimited ***
units: seconds since 1970-1-1 00:00:00
我使用了包ncdf.tools
中的函数提取时间并将其转换为时间序列分类的日期,但是我得到了错误的结果:
convertDateNcdf2R(id_579$dim$time$vals, units="seconds")
[75] "1846-07-03 05:04:51 UTC"
[76] "1846-07-03 05:05:01 UTC"
[77] "1846-07-03 05:05:06 UTC"
[78] "1846-07-03 05:05:11 UTC"
[79] "1846-07-03 05:05:16 UTC"
日期不应超过 1970 年。是否有更好的替代方法?
创建这个的函数是:
convertDateNcdf2R = function(
##title<< Convert netCDF time vector to POSIXct R date object
time.source ##<< numeric vector or netCDF connection: either a number of time units since
## origin or a netCDF file connection, In the latter case, the time
## vector is extracted from the netCDF file, This file, and especially the
## time variable, has to follow the CF netCDF conventions.
, units = 'days' ##<< character string: units of the time source. If the source
## is a netCDF file, this value is ignored and is read from that file.
, origin = as.POSIXct('1800-01-01', tz = 'UTC') ##<< POSIXct object:
## Origin or day/hour zero of the time source. If the source
## is a netCDF file, this value is ignored and is read from that file.
, time.format = c('%Y-%m-%d', '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M', '%Y-%m-%d %Z %H:%M', '%Y-%m-%d %Z %H:%M:%S')
)
##description<< This function converts a time vector from a netCDF file or a vector of Julian days (or seconds, minutes, hours)
## since a specified origin into a POSIXct R vector.
{
close.file = FALSE
if (class(time.source) == 'character') {
if (file.exists(time.source)) {
time.source = open.nc(time.source)
} else {
stop(paste('File ', time.source, ' is not existent!', sep = ''))
}
}
if (class(time.source) == 'NetCDF') {
attget.result <- try({
units.file <- infoNcdfAtts(time.source, 'time')[, 'value'][infoNcdfAtts(time.source, 'time')[, 'name'] == 'units']
origin.char <- sub('^.*since ', '', units.file)
units <- sub(' since.*', '', units.file)
}, silent = TRUE)
for (formatT in time.format) {
origin <- strptime(origin.char, format = formatT, tz = 'UTC')
if (!is.na(origin))
break
}
if (is.na(origin))
stop('Not possible to determine origin. Wrong format supplied?')
date.vec <- as.numeric(var.get.nc(time.source, 'time'))
} else {
if (!is.numeric(time.source))
stop('time.source needs to be numeric if not a netCDF file connection!')
date.vec <- time.source
}
if (!is.element(units, c('seconds', 'minutes', 'hours', 'days')))
stop(paste('Unit ', units, ' is not implemented.', sep = ''))
multiplicator <- switch(units, days = 60 * 60 * 24, hours = 60 * 60, minutes = 60, seconds = 1)
time.out <- origin + date.vec * multiplicator
if (origin < as.POSIXct('1582-10-30', tz = 'UTC'))
time.out <- time.out + 10 * 24 * 60 * 60
if (close.file)
close.nc(time.source)
##value<<
## POSIXct vector: time vector in native R format
return(time.out)
}
这是时间数据的一些示例:
time
1 1467435408
2 1467435418
3 1467435425
4 1467435431
5 1467435438
6 1467435444
我在使用不同类型的日历时遇到了类似的问题,但在我发现软件包 ncdf4.helpers 之后,现在一切都变得更加容易和快捷。一个例子:
> library(ncdf4)
> #open the netcdf file
> ncin<- nc_open("precip_GPCP_1998.nc")
> library(ncdf4.helpers)
> #obtain time dimension in date format
> Time_in_Date_format <- nc.get.time.series(f = ncin,
time.dim.name = "time")
> nc_close(ncin)
> Time_in_Date_format
[1] "1998-01-01" "1998-02-01" "1998-03-01" "1998-04-01" "1998-05-01"
[6] "1998-06-01" "1998-07-01" "1998-08-01" "1998-09-01" "1998-10-01"
[11] "1998-11-01" "1998-12-01"
我正在尝试将 netCDF 文件中的时间单位转换为正确的格式,但是,我得到了错误的输出。
我使用的数据有时间格式:
1 dimensions:
time Size:193458 *** is unlimited ***
units: seconds since 1970-1-1 00:00:00
我使用了包ncdf.tools
中的函数提取时间并将其转换为时间序列分类的日期,但是我得到了错误的结果:
convertDateNcdf2R(id_579$dim$time$vals, units="seconds")
[75] "1846-07-03 05:04:51 UTC"
[76] "1846-07-03 05:05:01 UTC"
[77] "1846-07-03 05:05:06 UTC"
[78] "1846-07-03 05:05:11 UTC"
[79] "1846-07-03 05:05:16 UTC"
日期不应超过 1970 年。是否有更好的替代方法?
创建这个的函数是:
convertDateNcdf2R = function(
##title<< Convert netCDF time vector to POSIXct R date object
time.source ##<< numeric vector or netCDF connection: either a number of time units since
## origin or a netCDF file connection, In the latter case, the time
## vector is extracted from the netCDF file, This file, and especially the
## time variable, has to follow the CF netCDF conventions.
, units = 'days' ##<< character string: units of the time source. If the source
## is a netCDF file, this value is ignored and is read from that file.
, origin = as.POSIXct('1800-01-01', tz = 'UTC') ##<< POSIXct object:
## Origin or day/hour zero of the time source. If the source
## is a netCDF file, this value is ignored and is read from that file.
, time.format = c('%Y-%m-%d', '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M', '%Y-%m-%d %Z %H:%M', '%Y-%m-%d %Z %H:%M:%S')
)
##description<< This function converts a time vector from a netCDF file or a vector of Julian days (or seconds, minutes, hours)
## since a specified origin into a POSIXct R vector.
{
close.file = FALSE
if (class(time.source) == 'character') {
if (file.exists(time.source)) {
time.source = open.nc(time.source)
} else {
stop(paste('File ', time.source, ' is not existent!', sep = ''))
}
}
if (class(time.source) == 'NetCDF') {
attget.result <- try({
units.file <- infoNcdfAtts(time.source, 'time')[, 'value'][infoNcdfAtts(time.source, 'time')[, 'name'] == 'units']
origin.char <- sub('^.*since ', '', units.file)
units <- sub(' since.*', '', units.file)
}, silent = TRUE)
for (formatT in time.format) {
origin <- strptime(origin.char, format = formatT, tz = 'UTC')
if (!is.na(origin))
break
}
if (is.na(origin))
stop('Not possible to determine origin. Wrong format supplied?')
date.vec <- as.numeric(var.get.nc(time.source, 'time'))
} else {
if (!is.numeric(time.source))
stop('time.source needs to be numeric if not a netCDF file connection!')
date.vec <- time.source
}
if (!is.element(units, c('seconds', 'minutes', 'hours', 'days')))
stop(paste('Unit ', units, ' is not implemented.', sep = ''))
multiplicator <- switch(units, days = 60 * 60 * 24, hours = 60 * 60, minutes = 60, seconds = 1)
time.out <- origin + date.vec * multiplicator
if (origin < as.POSIXct('1582-10-30', tz = 'UTC'))
time.out <- time.out + 10 * 24 * 60 * 60
if (close.file)
close.nc(time.source)
##value<<
## POSIXct vector: time vector in native R format
return(time.out)
}
这是时间数据的一些示例:
time
1 1467435408
2 1467435418
3 1467435425
4 1467435431
5 1467435438
6 1467435444
我在使用不同类型的日历时遇到了类似的问题,但在我发现软件包 ncdf4.helpers 之后,现在一切都变得更加容易和快捷。一个例子:
> library(ncdf4)
> #open the netcdf file
> ncin<- nc_open("precip_GPCP_1998.nc")
> library(ncdf4.helpers)
> #obtain time dimension in date format
> Time_in_Date_format <- nc.get.time.series(f = ncin,
time.dim.name = "time")
> nc_close(ncin)
> Time_in_Date_format
[1] "1998-01-01" "1998-02-01" "1998-03-01" "1998-04-01" "1998-05-01"
[6] "1998-06-01" "1998-07-01" "1998-08-01" "1998-09-01" "1998-10-01"
[11] "1998-11-01" "1998-12-01"