Gsub,提取一定数量的数字

时间:2017-04-16 19:57:57

标签: r regex gsub

很抱歉,如果我的问题在这里找到答案。不幸的是我找不到它。

我有一个字符串,其格式如下" 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))

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

2 个答案:

答案 0 :(得分:2)

tidyr具有非常强大的separate,可以很好地处理数据框/数据表,

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

以下是基础R中gsub的典型方法。在每种情况下,匹配字符串的前导部分,匹配捕获括号中的有趣部分,匹配其余部分。替换为&#34; \\ 1&#34;表示捕获的值

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))

答案 1 :(得分:2)

以下是一些基本选项:

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

(虽然最后一个是矢量列表,但您的消费格式略有不同。)