从一系列文件名中提取可变结构的日期,并将其作为日期变量(R)添加到源栅格中



我有一大系列的光栅,构成了气候数据的时间序列(1层/月(,我最终的目标是从中提取一系列坐标的值。我已经将它们作为列表从文件导入RStudio,然后堆叠它们:

Temp_list <- list.files('C:/Users/xxxx/Desktop/Project/climate_data/temp', full.names = TRUE) 
TempST <-  stack(Temp_list)

有>600层,它们在结构中被命名为:

CLIMATdata_temp_1_1988_V.1.5

CLIMATdata_temp_12_2001_V.1.5

即,月份列在变量类型(此处为temp(之后,年份之前。我遇到的问题是,10月之前的几个月被列为个位数(事先没有0(,而10月之后的几个月则被列为2位数。

我想循环浏览每一层,从文件名中提取月份和年份,然后将其转换为日期格式。

我希望从上述文件名中获得">1_1.1988"one_answers">12_2001",然后将这些转换为日期对象。

我知道我需要使用正则表达式来做到这一点,但我并不完全理解它的结构,而且我正在努力解决位数的差异。我尝试过以下代码,但没有任何成功:

for (i in TempST) {
Dt <- sub(pattern = '.*temp_(d+_d+).*', i) #also '^(?:.*_)?([0-9]{1:2})([0-9]{4})(?:..*)?$'
YrMo <- as.Date(dt, '%m_%Y')
i <- setZ(i, ym, 'date')
names(i) <- Dt
} 

我确信这是一个相当简单的解决方案,但我已经为此挣扎了一段时间。非常感谢你的帮助。

我认为您的问题是对包含数字的字符串进行排序,并将这些字符串视为数字而非字母顺序。然后提取部分名称并确定日期(这个问题与光栅无关(。还要注意,无论你怎么做,你都可以而且应该在整个向量上做,而不是在一个循环中。

示例数据

f <- sort(paste0("a_2010_", 1:12, "_b.tif"))
f <- c(f, gsub(2010, 2011, f))

使用字符串::str_sort

library(stringr)
ff <- str_sort(f, numeric=TRUE)

或者推出自己的:

x <- data.frame(do.call(rbind, strsplit(basename(f), "_")))
x[,2] <- as.numeric(x[,2])
x[,3] <- as.numeric(x[,3])
i <- order(x[,2], x[,3])
ff <- f[i]
ff
# [1] "a_2010_1_b.tif"  "a_2010_2_b.tif"  "a_2010_3_b.tif"  "a_2010_4_b.tif" 
# [5] "a_2010_5_b.tif"  "a_2010_6_b.tif"  "a_2010_7_b.tif"  "a_2010_8_b.tif" 
# [9] "a_2010_9_b.tif"  "a_2010_10_b.tif" "a_2010_11_b.tif" "a_2010_12_b.tif"
#[13] "a_2011_1_b.tif"  "a_2011_2_b.tif"  "a_2011_3_b.tif"  "a_2011_4_b.tif" 
#[17] "a_2011_5_b.tif"  "a_2011_6_b.tif"  "a_2011_7_b.tif"  "a_2011_8_b.tif" 
#[21] "a_2011_9_b.tif"  "a_2011_10_b.tif" "a_2011_11_b.tif" "a_2011_12_b.tif"

获取日期:

ff <- str_sort(f, numeric=TRUE)
x <- data.frame(do.call(rbind, strsplit(basename(ff), "_")))
dates <- apply(cbind(x[,2:3], 15), 1, function(i) paste(i, collapse="-"))
d <- as.Date(dates) 
d
# [1] "2010-01-15" "2010-02-15" "2010-03-15" "2010-04-15" "2010-05-15"
# [6] "2010-06-15" "2010-07-15" "2010-08-15" "2010-09-15" "2010-10-15"
#[11] "2010-11-15" "2010-12-15" "2011-01-15" "2011-02-15" "2011-03-15"
#[16] "2011-04-15" "2011-05-15" "2011-06-15" "2011-07-15" "2011-08-15"
#[21] "2011-09-15" "2011-10-15" "2011-11-15" "2011-12-15"

或者,从文件名中删除你不想要的内容(一旦你有了日期,就很容易排序,所以你不需要预先排序(

xf <- gsub("a_", "", f)
xf <- gsub("_b.tif", "", xf)
dd <- as.Date(paste0(xf, "_15"), "%Y_%m_%d")
i <- order(dd)
ff <- ff[i]
dd <- dd[i]

或者,如果你真的不在乎订单,并且你知道自己有几年的时间,你可以做

years <- 2010:2011
d <- paste0(rep(years,each=12), "-", rep(c(1,10:12,2:9), length(years)), "-", 15) 
as.Date(d)

regex有点棘手,但这里有一种部分使用它的方法

g <- gsub("[^[:digit:]]", "", f)
as.Date(paste0(substr(g, 1, 4), "-", substr(g, 5, 7), "-", 15))

您可以使用解决问题

sub('.*temp_(\d+_\d+).*', '\1', i)

这里,

  • .*temp_匹配任何零个或多个字符,尽可能多,然后匹配temp_字符串
  • (d+_d+)将任意一个或多个数字、_以及任意一个或者多个数字捕获到组1中
  • .*-任何零个或多个字符,尽可能多

1替换仅在结果中保留组1的值。

最新更新