You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R环境下如何从Sentinel 2栅格文件名数值串中提取YYYYMMDD格式日期

解决方案

1 日期提取逻辑修正

你之前用全局替换数字、删除31的方法稳定性极差,很容易误删日期里的数字(比如日期为1月31日时会被错误替换)。Sentinel-2产品的文件名是固定的下划线分隔规则,格式为:
MGRS tile号_观测时间_波段号.jp2
其中观测时间字段的前8位就是你需要的YYYYMMDD格式日期,直接按规则拆分即可,无需复杂替换:

# 示例:从文件名T31UER_20210722T105619_B04.jp2提取日期
b4_file <- "T31UER_20210722T105619_B04.jp2"
# 按下划线拆分,取第二个字段的前8位
date_str <- substr(strsplit(b4_file, "_")[[1]][2], 1, 8)
# 输出为20210722

2 原代码问题修正

你的原有代码存在多处逻辑错误:

  • list.files写在循环内部,每次循环都会重复扫描文件夹,效率极低
  • 未将文件名读取为栅格对象,直接对字符串做算术运算会报错
  • NDVI计算公式完全错误,原代码分子分母相同,输出结果恒为1,正确公式为 NDVI = (近红外波段-红波段)/(近红外波段+红波段)
  • 栅格保存逻辑错误,未指定单独的输出文件名,会导致结果被反复覆盖

3 可直接运行的完整代码

library(raster)

# 提前配置路径
input_dir <- "C:/Users/Perrin/Desktop/INRA/Raster/BDA/Images en vrac"
# 建议单独新建输出文件夹,避免和原始栅格文件混淆
output_dir <- "C:/Users/Perrin/Desktop/INRA/Raster/BDA/Images en vrac"

# 提前读取所有B04文件,无需循环内重复扫描
all_b4 <- list.files(path = input_dir, pattern = "B04.jp2$", full.names = TRUE)

# 循环处理每一组数据
for (i in seq_along(all_b4)) {
  # 提取当前B04对应的日期
  b4_name <- basename(all_b4[i])
  date_str <- substr(strsplit(b4_name, "_")[[1]][2], 1, 8)
  
  # 匹配同日期的B05文件
  b5_path <- list.files(path = input_dir, pattern = paste0(date_str, ".*B05.jp2$"), full.names = TRUE)
  if (length(b5_path) == 0) {
    message("日期", date_str, "未找到对应的B05文件,跳过")
    next
  }
  
  # 读取栅格数据
  b4_rast <- raster(all_b4[i])
  b5_rast <- raster(b5_path)
  
  # 计算NDVI,强制转为浮点型避免计算错误
  ndvi_rast <- (b5_rast - b4_rast) / (b5_rast + b4_rast)
  
  # 保存结果
  output_path <- file.path(output_dir, paste0("NDVI_", date_str, ".tif"))
  writeRaster(ndvi_rast, filename = output_path, format = "GTiff", overwrite = TRUE)
  message("日期", date_str, "的NDVI计算完成,已保存至", output_path)
}

内容的提问来源于stack exchange,提问作者Perrin Remonté

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:36:02