如何使用 R 在文件夹中的多个文件名的年份数字后移动月份数字?

How to move month digits after year digits for multiple filenames in a folder with R?

我有一个文件夹,其中包含从 1950 年 1 月到 2018 年 12 月的多个光栅 .tif 文件。但是,它们的命名方式是先按月份再按年份(见下文):

[1] "./WI_only_cmi60_01_1950.tif" "./WI_only_cmi60_01_1951.tif" "./WI_only_cmi60_01_1952.tif"

[4] "./WI_only_cmi60_01_1953.tif" "./WI_only_cmi60_01_1954.tif" "./WI_only_cmi60_01_1955.tif"

[7] "./WI_only_cmi60_01_1956.tif" "./WI_only_cmi60_01_1957.tif" "./WI_only_cmi60_01_1958.tif"

...


[820] "./WI_only_cmi60_12_2010.tif" "./WI_only_cmi60_12_2011.tif" "./WI_only_cmi60_12_2012.tif"

[823] "./WI_only_cmi60_12_2013.tif" "./WI_only_cmi60_12_2014.tif" "./WI_only_cmi60_12_2015.tif"

[826] "./WI_only_cmi60_12_2016.tif" "./WI_only_cmi60_12_2017.tif" "./WI_only_cmi60_12_2018.tif"

当我将这些带入 R 并使用 Raster 包堆叠这些时:

# list tif files in working directory
tifs <- list.files(pattern = ".tif$", full.names = TRUE)

# stack tifs in working directory
rstack <- stack(tifs)

它们按所有一月的 .tif 文件排序,然后是所有二月的 .tif 文件等,当我每年需要它们时,然后每个月(按时间顺序从 1950 年 1 月到 2018 年 12 月)。

有没有办法重命名这些文件,其中可以重新排列文件名的顺序,以便将每个文件名的字符 15 和 16 移动到年份字符(18、19、20、21)之后?

即列出的第一个文件名将从

"./WI_only_cmi60_01_1950.tif"

"./WI_only_cmi60_1950_01.tif"

我们可以作为一个组捕获并安排反向引用

sub("(\d+)_(\d+)(\.tif)", "\2_\1\3", "./WI_only_cmi60_01_1950.tif")

-输出

[1] "./WI_only_cmi60_1950_01.tif"

使用 strsplit.

x <- "./WI_only_cmi60_01_1950.tif"
revfun <- function(x) {
  r <- rev(el(strsplit(x, '')))
  Reduce(paste0, rev(r[c(1:4, 10:12, 5:9, 13:length(r))]))
}
revfun(x)
# [1] "./WI_only_cmi60_1950_01.tif"

我不会重命名文件,而是适当地对文件名进行排序。在长期 运行 的重现性和更新方面,这应该是一个更好的方法。

示例(未排序)

ff <- c("./WI_only_cmi60_01_1950.tif","./WI_only_cmi60_01_1951.tif", "./WI_only_cmi60_01_1952.tif", 
"./WI_only_cmi60_06_1950.tif", "./WI_only_cmi60_06_1951.tif", "./WI_only_cmi60_06_1952.tif", 
"./WI_only_cmi60_12_1950.tif", "./WI_only_cmi60_12_1951.tif", "./WI_only_cmi60_12_1952.tif")

使用 Ak运行 的表达式

i <- sub("(\d+)_(\d+)(\.tif)", "\2_\1\3", ff)
fs <- ff[order(i)]
fs
#[1] "./WI_only_cmi60_01_1950.tif" "./WI_only_cmi60_06_1950.tif"
#[3] "./WI_only_cmi60_12_1950.tif" "./WI_only_cmi60_01_1951.tif"
#[5] "./WI_only_cmi60_06_1951.tif" "./WI_only_cmi60_12_1951.tif"
#[7] "./WI_only_cmi60_01_1952.tif" "./WI_only_cmi60_06_1952.tif"
#[9] "./WI_only_cmi60_12_1952.tif"

实现相同目标的更基本方法

x <- gsub("WI_only_cmi60_", "", basename(ff))
d <- paste(substr(x, 4, 7), substr(x, 1, 2), sep="-")
i <- order(d)
ff[i]

鉴于模式似乎相当简单(69 年,每个 12 个月)你也可以这样做(用你所有的文件)

i <- rep(1:69, 12)
fs <- ff[i]

(始终仔细检查结果!)

我使用的代码如下 - 通过 akrun 和 Robert Hijmans 给出的答案 - 但我想阐明我是如何使用这些答案来读取工作目录中的所有 .tif 文件并堆叠这些文件的:

setwd("C:/...")

# list tif files in working directory
ff <- list.files(pattern = ".tif$", full.names = TRUE) 
i <- sub("(\d+)_(\d+)(\.tif)", "\2_\1\3", ff) 
fs <- ff[order(i)] 

library(raster)

# create stack of tif files
rstack <- stack(fs)