R语言实战——一些批量对地理数据进行操作的方法

各位朋友在进行数据处理时,当有多张栅格影像时,如果我们都要进行同一操作时,一张一张做很繁琐,用ArcGIS模型构建器是一种比较好的方法。当然,今天小编新学了R语言上面进行批量裁剪,一起来学习一下吧!

一、批量裁剪

当我们有一张栅格数据时,需要按照特定的空间范围进行矢量数据裁剪时,应该怎么办?

话不多说,直接上代码:

R 复制代码
裁剪
library(terra)
# 定义栅格文件和矢量数据路径
raster_file <- "H:/TEMData/Result/mean_output.tif"  # 栅格文件路径
vector_file <- "H:/shpfile"  # 矢量数据路径
output_file <- "H:/TEMData/Result/cropped_output.tif"    # 输出文件路径

# 读取栅格数据
raster_data <- rast(raster_file)

# 读取矢量数据
vector_data <- vect(vector_file)

# 设置栅格数据的坐标系(如果需要)
if (is.na(crs(raster_data))) {
  crs(raster_data) <- crs(vector_data)
}

# 使用 crop 和 mask 函数进行裁剪
masked_data <- crop(raster_data, vector_data) %>% 
  mask(., vector_data)

# 写入裁剪后的数据到输出文件
writeRaster(masked_data, output_file, overwrite = TRUE)

cat("Cropped raster saved to:", output_file, "\n")

# 可选:显示裁剪后的栅格
plot(masked_data, main = "Cropped Raster", col = terrain.colors(20))

上面是单张栅格影像的处理,那如果我有20张,有50张呢?那我们来写个循环吧。

R 复制代码
library(terra)
library(magrittr)  # 加载管道操作符

# 批量读取tif
folder <- "F:/shiyan1/"
# 输出文件夹路径,保存裁剪后的数据
output_folder <- "F:/result1/"

# 创建输出文件夹
if (!dir.exists(output_folder)) { 
  dir.create(output_folder)
}

# 获取所有TIF文件
tiff_files <- list.files(path = folder, pattern = "\\.tif$", full.names = TRUE)

# 读取 Shapefile 数据
shp_data <- vect("F:/hlbe")

# 循环处理每个TIF文件
for (tiff_file in tiff_files) { 
  # 从文件名中提取文件名(不包括路径和扩展名) 
  output_name <- tools::file_path_sans_ext(basename(tiff_file)) 
  
  # 读取 GeoTIFF 数据
  raster_data <- rast(tiff_file) 
  
  # 使用 mask 函数进行按照 Shapefile 进行的遮罩
  masked_data <- crop(raster_data, shp_data) %>% 
    mask(., shp_data) 
  
  # 构建输出文件路径
  output_path <- file.path(output_folder, paste0(output_name, ".tif")) 
  
  # 写入裁剪后的数据到输出文件 
  writeRaster(masked_data, output_path, overwrite = TRUE) 
  
  cat("File", tiff_file, "processed and saved to", output_path, "\n")
}

# 加载显示裁剪后的数据
output_rasters <- list.files(path = output_folder, pattern = "\\.tif$", full.names = TRUE)
if (length(output_rasters) > 0) {
  plot(rast(output_rasters))
} else {
  cat("No raster files found in the output folder.\n")
}

上面写了一个for循环,用mask函数进行掩膜处理,这样子就可以实现批量裁剪啦。

不过大家要注意,在进行代码梳理的时候,一定要注意,矢量空间范围和栅格数据的坐标系要统一,不然可能因为空间范围不同,没有重叠,或者坐标系冲突,从而产生错误结果。代码可以直接用,要改的地方就是文件夹的读取和导出,大家要复制自己所在数据地址哈!

二、定义坐标系

既然上面讲到了坐标系要统一,那么我们想到,怎么样对一张栅格影像进行坐标系定义呢?

我们上代码:

R 复制代码
library(terra)

# 定义输入文件夹和输出文件夹
folder <- "F:/shiyan1/"
output_folder <- "F:/result1/"

# 创建输出文件夹
if (!dir.exists(output_folder)) {
  dir.create(output_folder)
}

# 获取所有TIF文件
tiff_files <- list.files(path = folder, pattern = "\\.tif$", full.names = TRUE)

# 循环处理每个TIF文件
for (tiff_file in tiff_files) {
  # 读取 GeoTIFF 数据
  raster_data <- rast(tiff_file)
  
  # 设置坐标系为 WGS 1984
  crs(raster_data) <- "EPSG:4326"
  
  # 构建输出文件路径
  output_path <- file.path(output_folder, basename(tiff_file))
  
  # 写入设置坐标系后的数据到输出文件 
  writeRaster(raster_data, output_path, overwrite = TRUE) 
  
  cat("File", tiff_file, "processed and saved with WGS 1984 coordinate system to", output_path, "\n")
}

这里我们将栅格数据定义为WGS1984坐标系,大家找到要定义的坐标系的EPSG代码,改一改就行啦。

三、批量转换数据格式

在进行数据处理时,tif格式的数据是常用的数据格式,我们从一些网站下面下载的数据可能是GRID格式或者其他格式,小编在处理多年风速数据的时候就遇到了这个问题,如果你需要将多张其他格式的数据转换成tif格式,应该怎么做?

我们上代码:

R 复制代码
# 加载必要的包
library(terra)

# 设置输入和输出文件夹
input_folder <- "H:/VData/"  # 输入 ADF 文件夹路径
output_folder <- "H:/tem/output/"  # 输出 TIFF 文件夹路径

# 创建输出文件夹(如果不存在)
if (!dir.exists(output_folder)) {
  dir.create(output_folder)
}

# 获取所有 ADF 文件夹
adf_dirs <- list.dirs(path = input_folder, full.names = TRUE, recursive = FALSE)

# 循环处理每个 ADF 文件夹
for (adf_dir in adf_dirs) {
  # 检查是否存在 ADF 文件
  adf_files <- list.files(adf_dir, pattern = "\\.adf$", full.names = TRUE)
  if (length(adf_files) > 0) {
    # 读取 ADF 数据
    raster_data <- rast(adf_dir)
    
    # 从文件夹名中提取输出 TIFF 文件名
    output_name <- tools::file_path_sans_ext(basename(adf_dir))  # 不包括后缀
    output_file <- file.path(output_folder, paste0(output_name, ".tif"))
    
    # 将 ADF 数据保存为 TIFF 格式
    writeRaster(raster_data, output_file, overwrite = TRUE)  # 不需要指定 format
    
    cat("Converted:", adf_dir, "to", output_file, "\n")
  } else {
    cat("No ADF files found in:", adf_dir, "\n")
  }
}

通过上述代码,我们可以实现对数据的格式转换,中间我们用if函数检查了一下我们的文件夹里面是否存在我们需要转换的数据格式文件,如果没有会报出,这时我们需要对文件夹重新整理。小编在处理的时候,一开始有info文件夹在里头,R语言读不了,后面吧info文件删除之后,就能够开始读取了。

四、栅格计算

当我们有连续20年的数据,如果需要进行均值计算时,怎么办?

R 复制代码
library(terra)

# 定义输入文件夹
input_folder <- "H:/TEMData/Data"

# 获取所有 TIF 文件
tiff_files <- list.files(path = input_folder, pattern = "\\.tif$", full.names = TRUE)

# 读取第一个栅格数据以获取参考范围和分辨率
reference_raster <- rast(tiff_files[1])

# 创建一个空的列表来存储对齐后的栅格数据
aligned_rasters <- list(reference_raster)

# 循环处理其他栅格文件
for (tiff_file in tiff_files[-1]) {
  # 读取栅格数据
  raster_data <- rast(tiff_file)
  
  # 对齐栅格数据到参考栅格的范围和分辨率
  aligned_raster <- project(raster_data, reference_raster)
  
  # 添加对齐后的栅格到列表
  aligned_rasters <- c(aligned_rasters, list(aligned_raster))
}

# 将对齐后的栅格合并为一个栅格堆栈
raster_stack <- rast(aligned_rasters)

# 计算均值
mean_raster <- app(raster_stack, fun = mean, na.rm = TRUE)

# 构建输出文件路径
output_path <- "H:/TEMData/Result/mean_output.tif"

# 写入均值栅格数据到输出文件
writeRaster(mean_raster, output_path, overwrite = TRUE)

# 显示均值栅格
plot(mean_raster, main = "Mean Raster", col = terrain.colors(20))

cat("Mean raster saved to:", output_path, "\n")

这里是结果:

如果是要进行求和呢?

我们以逐月日照数据为例,来看看怎么实现?

R 复制代码
library(terra)

# 设置输入文件夹路径
input_folder <- "H:/ssd/2013"
output_file <- "H:/ssd/result/annual_sum_raster.tif"

# 获取所有 TIF 文件
raster_files <- list.files(path = input_folder, pattern = "\\.tif$", full.names = TRUE)

if (length(raster_files) == 0) {
  stop("No TIF files found in the specified folder.")
}

annual_sum_raster <- NULL

# 循环处理每个栅格影像
for (raster_file in raster_files) {
  current_raster <- rast(raster_file)
  
  if (is.null(annual_sum_raster)) {
    annual_sum_raster <- current_raster
  } else {
    annual_sum_raster <- annual_sum_raster + current_raster
  }
  
  gc()  # 垃圾回收
}

writeRaster(annual_sum_raster, output_file, overwrite = TRUE)
cat("Annual sum raster saved to:", output_file, "\n")
plot(annual_sum_raster, main = "Annual Sum Raster")

需要注意的是年度合成数据因为计算量比较大,如果你的栅格有多张,可能算不出来,我们就需要设计一个垃圾回收的机制,来减少不必要的内存消耗,这里是月日照数据合成年总和数据的结果:

好了,今天我们的学习就到这里结束了,希望对大家有帮助!

我们是梧桐GIS,致力于分享数据处理的优质教程,谢谢大家关注!

相关推荐
计算机学姐12 分钟前
基于Python的高校成绩分析管理系统
开发语言·vue.js·后端·python·mysql·pycharm·django
VertexGeek14 分钟前
Rust学习(三):rust基础Ⅱ
开发语言·学习·rust
一个数据小开发20 分钟前
业务开发问题之ConcurrentHashMap
java·开发语言·高并发·map
三小尛1 小时前
插入排序(C语言)
c语言·开发语言
南宫理的日知录1 小时前
106、Python并发编程:深入浅出理解线程池的内部实现原理
开发语言·python·学习·编程学习
WolvenSec1 小时前
C/C++逆向:结构体逆向分析
c语言·开发语言·c++·网络安全
谢尔登1 小时前
前端开发调试之 PC 端调试
开发语言·前端
每天吃饭的羊1 小时前
在循环中只set一次
开发语言·前端·javascript
江梦寻3 小时前
解决SLF4J: Class path contains multiple SLF4J bindings问题
java·开发语言·spring boot·后端·spring·intellij-idea·idea
每天写点bug3 小时前
golang 常用的占位符 %w, %v, %s
开发语言·后端·golang