将 hdf 文件读取到 R 并将其转换为 geoTIFF 栅格



我正在尝试将MODIS 17数据文件读取到R中,对其进行操作(裁剪等),然后将它们另存为geoTIFF。 数据文件以.hdf格式出现,似乎没有一种简单的方法将它们读入 R。

与其他主题相比,那里没有很多建议,其中大部分都是几年前的。 其中一些还建议使用其他程序,但我想坚持只使用 R。

人们使用什么包来处理 R 中的.hdf文件?

好的,所以我的MODIS hdf文件是hdf4而不是hdf5格式。 发现这一点非常困难,MODIS没有在他们的网站上提到它,但在各种博客和堆栈交换帖子中有一些提示。 最后,我不得不下载HDFView才能确定。

R不做hdf4文件,几乎所有的软件包(如rgdal)只支持hdf5文件。 有一些关于下载驱动程序和从源代码编译 rgdal 的帖子,但这一切似乎都相当复杂,这些帖子是针对 MAC 或 Unix 的,我使用的是 Windows。

基本上,gdalUtils包中的gdal_translate对于任何想要在 R 中使用 hdf4 文件的人来说都是节省的恩典。 它将 hdf4 文件转换为 geoTIFF,而无需将它们读取到 R 中。 这意味着您根本无法操纵它们,例如通过裁剪它们,因此值得获得最小的磁贴(通过 Reverb 之类的东西用于 MODIS 数据)以最大限度地减少计算时间。

下面是代码的示例:

library(gdalUtils)
# Provides detailed data on hdf4 files but takes ages
gdalinfo("MOD17A3H.A2000001.h21v09.006.2015141183401.hdf")
# Tells me what subdatasets are within my hdf4 MODIS files and makes them into a list
sds <- get_subdatasets("MOD17A3H.A2000001.h21v09.006.2015141183401.hdf")
sds
[1] "HDF4_EOS:EOS_GRID:MOD17A3H.A2000001.h21v09.006.2015141183401.hdf:MOD_Grid_MOD17A3H:Npp_500m"   
[2] "HDF4_EOS:EOS_GRID:MOD17A3H.A2000001.h21v09.006.2015141183401.hdf:MOD_Grid_MOD17A3H:Npp_QC_500m"
# I'm only interested in the first subdataset and I can use gdal_translate to convert it to a .tif
gdal_translate(sds[1], dst_dataset = "NPP2000.tif")
# Load and plot the new .tif
rast <- raster("NPP2000.tif")
plot(rast)
# If you have lots of files then you can make a loop to do all this for you
files <- dir(pattern = ".hdf")
files
 [1] "MOD17A3H.A2000001.h21v09.006.2015141183401.hdf" "MOD17A3H.A2001001.h21v09.006.2015148124025.hdf"
 [3] "MOD17A3H.A2002001.h21v09.006.2015153182349.hdf" "MOD17A3H.A2003001.h21v09.006.2015166203852.hdf"
 [5] "MOD17A3H.A2004001.h21v09.006.2015099031743.hdf" "MOD17A3H.A2005001.h21v09.006.2015113012334.hdf"
 [7] "MOD17A3H.A2006001.h21v09.006.2015125163852.hdf" "MOD17A3H.A2007001.h21v09.006.2015169164508.hdf"
 [9] "MOD17A3H.A2008001.h21v09.006.2015186104744.hdf" "MOD17A3H.A2009001.h21v09.006.2015198113503.hdf"
[11] "MOD17A3H.A2010001.h21v09.006.2015216071137.hdf" "MOD17A3H.A2011001.h21v09.006.2015230092603.hdf"
[13] "MOD17A3H.A2012001.h21v09.006.2015254070417.hdf" "MOD17A3H.A2013001.h21v09.006.2015272075433.hdf"
[15] "MOD17A3H.A2014001.h21v09.006.2015295062210.hdf"
filename <- substr(files,11,14)
filename <- paste0("NPP", filename, ".tif")
filename
[1] "NPP2000.tif" "NPP2001.tif" "NPP2002.tif" "NPP2003.tif" "NPP2004.tif" "NPP2005.tif" "NPP2006.tif" "NPP2007.tif" "NPP2008.tif"
[10] "NPP2009.tif" "NPP2010.tif" "NPP2011.tif" "NPP2012.tif" "NPP2013.tif" "NPP2014.tif"
i <- 1
for (i in 1:15){
  sds <- get_subdatasets(files[i])
  gdal_translate(sds[1], dst_dataset = filename[i])
}

现在,您可以使用栅格包中的raster等方法将.tif文件读入 R 并正常工作。 我已经根据我使用 QGIS 手动转换的一些文件检查了生成的文件,并且它们匹配,因此我相信代码正在做我认为的事情。 感谢Loïc Dutrieux和这个帮助!

这些天您可以将 terra 包与 HDF 文件一起使用

获取子数据集

 library(terra)
 s <- sds("file.hdf")
 s

可以像这样提取为SpatRasters

s[1]

或者像这样创建所有子数据集的 SpatRaster

r <- rast("file.hdf")

以下内容对我有用。这是一个简短的程序,只接受输入文件夹名称。确保您知道所需的子数据。我对子数据 1 感兴趣。

library(raster)
library(gdalUtils)
inpath <- "E:/aster200102/ast_200102"
setwd(inpath)
filenames <- list.files(,pattern=".hdf$",full.names = FALSE)
for (filename in filenames)
{
     sds <- get_subdatasets(filename)
     gdal_translate(sds[1], dst_dataset=paste0(substr(filename, 1, nchar(filename)-4) ,".tif"))
}
使用

NASA 提供的 HEG 工具包将 hdf 文件转换为 geotiff,然后使用任何包(例如"光栅")读取文件。我对旧的和新的 hdf 文件都做同样的事情。

这是链接: https://newsroom.gsfc.nasa.gov/sdptoolkit/HEG/HEGHome.html

看看这里支持的NASA产品:https://newsroom.gsfc.nasa.gov/sdptoolkit/HEG/HEGProductList.html

希望这有帮助。

这个脚本非常有用,我设法使用它转换了一批 36 个文件。但是,我的问题是转换似乎不正确。当我使用 ArcGIS "创建 NetCDF 栅格图层工具"执行此操作时,我得到了不同的结果 + 我能够使用简单的公式将数字从开尔文转换为 C:栅格值 * 0.02 - 273.15。对于 R 转换的结果,我在转换后没有得到正确的结果,这让我相信 ArcGIS 转换很好,R 转换返回错误。

library(gdalUtils)
library(raster)
setwd("D:/Data/Climate/MODIS")
# Get a list of sds names
sds <- get_subdatasets('MOD11C3.A2009001.006.2016006051904.hdf')
# Isolate the name of the first sds
name <- sds[1]
filename <- 'Rasterinr.tif'
gdal_translate(sds[1], dst_dataset = filename)
# Load the Geotiff created into R
r <- raster(filename)
# Identify files to read:
rlist=list.files(getwd(), pattern="hdf$", full.names=FALSE)

# Substract last 5 digits from MODIS filename for use in a new .img filename
substrRight <- function(x, n){
        substr(x, nchar(x)-n+1, nchar(x))
}
filenames0 <- substrRight(rlist,9)
# Suffixes for MODIS files for identyfication:
filenamessuffix <- substr(filenames0,1,5)
listofnewnames <- c("2009.01.MODIS_","2009.02.MODIS_","2009.03.MODIS_","2009.04.MODIS_","2009.05.MODIS_",
                    "2009.06.MODIS_","2009.07.MODIS_","2009.08.MODIS_","2009.09.MODIS_","2009.10.MODIS_",
                    "2009.11.MODIS_","2009.12.MODIS_",
                    "2010.01.MODIS_","2010.02.MODIS_","2010.03.MODIS_","2010.04.MODIS_","2010.05.MODIS_",
                    "2010.06.MODIS_","2010.07.MODIS_","2010.08.MODIS_","2010.09.MODIS_","2010.10.MODIS_",
                    "2010.11.MODIS_","2010.12.MODIS_",
                    "2011.01.MODIS_","2011.02.MODIS_","2011.03.MODIS_","2011.04.MODIS_","2011.05.MODIS_",
                    "2011.06.MODIS_","2011.07.MODIS_","2011.08.MODIS_","2011.09.MODIS_","2011.10.MODIS_",
                    "2011.11.MODIS_","2011.12.MODIS_")
# Final new names for converted files:
newnames <- vector()
for (i in 1:length(listofnewnames)) {
        newnames[i] <- paste0(listofnewnames[i],filenamessuffix[i],".img")
}
# Loop converting files to raster from NetCDF
for (i in 1:length(rlist)) {
        sds <- get_subdatasets(rlist[i])
        gdal_translate(sds[1], dst_dataset = newnames[i])
}

最新更新