Gsub,提取一定数量的数字

Gsub, extract certain amount of digits

抱歉,如果这里某处有我的问题的答案。可惜没找到。

我有一个具有以下形式的字符串 "ANNNNNNN.tif",其中 A 只是一个字母,N 是一个数字。一排有7位数字。

new <- c("A2000001.tif" ,"A2000002.tif", "A2000003.tif", "A2000004.tif", "A2000005.tif", "A2000006.tif")

我想从中获取年份和月份的值。前 4 位数字代表年份,后 2 位代表月份。例如。我写这个是为了得到一个年份值

year1 <- gsub("([0-9]){3,4}?.*$", "", new)
year <- as.numeric(gsub("A", "", year1))

但我想它可以写得更短一些,但我仍然很难获得一个月的价值。

UPD:我写这篇文章是为了一个月。

month1 <- gsub("^*.([0-9]){6,7}?", "\1", new)
month <- as.numeric(gsub(".tif", "", month1))

但仍然出于学习目的,我想知道如何以更好的方式做到这一点。

tidyr 具有非常强大的 separate,适用于数据 frames/data 表,

new <- c("A2000001.tif" ,"A2000002.tif", "A2000003.tif", "A2000004.tif", "A2000005.tif", "A2000006.tif")

library(tidyr)

df <- as.data.frame(new) %>%
  separate(new, into = c("letter", "year", "extra", "month", "extension"), sep=c(1,5,6,8), remove = FALSE) %>%
  select(-extra, -extension)

df         

#            new letter year month
# 1 A2000001.tif      A 2000    01
# 2 A2000002.tif      A 2000    02
# 3 A2000003.tif      A 2000    03
# 4 A2000004.tif      A 2000    04
# 5 A2000005.tif      A 2000    05
# 6 A2000006.tif      A 2000    06

以下是 gsub 在 base R 中的典型方法。在每种情况下,尽可能多地匹配字符串的前导部分,匹配捕获括号中感兴趣的部分,匹配其余部分。替换为“\\1”表示捕获的值

new <- c("A2000001.tif" ,"A2000002.tif", "A2000003.tif", "A2000004.tif", "A2000005.tif", "A2000006.tif")
letter <- gsub("(.).*", "\1", new)
year <- as.numeric(gsub(".(\d{4}).*", "\1", new))
month <- as.numeric(gsub(".\d{4}.(\d{2}).+", "\1", new))

以下是一些基本选项:

new <- c("A2000001.tif" ,"A2000002.tif", "A2000003.tif",
         "A2000004.tif", "A2000005.tif", "A2000006.tif")

假设它们始终位于字符串中的相同位置:

as.integer(substr(new, 2, 5))
# [1] 2000 2000 2000 2000 2000 2000
as.integer(substr(new, 7, 8))
# [1] 1 2 3 4 5 6

更具适应性,假设它们总是跟在非数字(年)之后或在点(月)之前:

as.integer(sub("^[^0-9]([0-9]{4}).*", "\1", new))
# [1] 2000 2000 2000 2000 2000 2000
as.integer(sub(".*([0-9]{2})\..*", "\1", new))
# [1] 1 2 3 4 5 6

提取所有数字并对它们做一些花哨的数学计算:

x <- as.integer(gsub("[^0-9]", "", new))
x %/% 1000
# [1] 2000 2000 2000 2000 2000 2000
x %% 100
# [1] 1 2 3 4 5 6

超级强大的正则表达式提取 (https://xkcd.com/1171/):

lapply(
  regmatches(new,
             gregexpr("(?<![0-9])[0-9]{4}|[0-9]{2}(?![0-9])", new, perl = TRUE)),
  as.integer
)
# [[1]]
# [1] 2000    1
# [[2]]
# [1] 2000    2
# [[3]]
# [1] 2000    3
# [[4]]
# [1] 2000    4
# [[5]]
# [1] 2000    5
# [[6]]
# [1] 2000    6

(虽然最后一个是矢量列表,但格式略有不同,供您使用。)