6

我正在尝试使用 R 提取文件名的一部分,我对如何从这里进行此操作有一个模糊的想法:extract part of a file name in R 但是我不能完全让它在我的文件名列表中工作

文件名示例:

"Species Count (2011-12-15-07-09-39).xls"
"Species Count 0511.xls"
"Species Count 151112.xls" 
"Species Count1011.xls" 
"Species Count2012-01.xls" 
"Species Count201207.xls" 
"Species Count2013-01-15.xls"  

有些文件名在 Species Count 和日期之间有一个空格,有些没有空格,它们的长度不同,有些包含括号。我只想提取文件名的数字部分并保留-。因此,例如对于上面的数据,我将拥有:

预期输出:

2011-12-15-07-09-39 , 0511 , 151112 , 1011 , 2012-01 , 201207 , 2013-01-15
4

4 回答 4

7

这是一种方法:

regmatches(tt, regexpr("[0-9].*[0-9]", tt))

我假设您的文件名中没有其他数字。因此,我们只搜索数字的开头并使用贪心运算符.*,以便捕获最后一个数字之前的所有内容。这是使用regexprwhich 将获得匹配的位置来完成的。然后我们使用regmatches从这些匹配的位置中提取(子)字符串。


哪里tt是:

tt <- c("Species Count (2011-12-15-07-09-39).xls", "Species Count 0511.xls", 
        "Species Count 151112.xls", "Species Count1011.xls", 
        "Species Count2012-01.xls", "Species Count201207.xls", 
        "Species Count2013-01-15.xls")

基准测试:

注意:Windows 和 *nix 机器之间的基准测试结果可能会有所不同(正如 @Hansi 在下面的注释下指出的那样)。

那里有一些不错的答案。所以,是时候进行基准测试了:)

tt <- rep(tt, 1e5) # tt is from above

require(microbenchmark)
require(stringr)
aa <- function() regmatches(tt, regexpr("[0-9].*[0-9]", tt))
bb <- function() gsub("[A-z \\.\\(\\)]", "", tt)
cc <- function() str_extract(tt,'([0-9]|[0-9][-])+')

microbenchmark(arun <- aa(), agstudy <- cc(), Jean <- bb(), times=25)
Unit: seconds
            expr      min       lq   median       uq       max neval
    arun <- aa() 1.951362 2.064055 2.198644 2.397724  3.236296    25
 agstudy <- cc() 2.489993 2.685285 2.991796 3.198133  3.762166    25
    Jean <- bb() 7.824638 8.026595 9.145490 9.788539 10.926665    25

identical(arun, agstudy) # TRUE
identical(arun, Jean) # TRUE
于 2013-08-06T13:29:29.737 回答
5

使用该函数gsub()删除所有字母、空格、句点和括号。然后你会留下数字和连字符。例如,

x <- c("Species Count (2011-12-15-07-09-39).xls", "Species Count 0511.xls", 
    "Species Count 151112.xls", "Species Count1011.xls", "Species Count2012-01.xls", 
    "Species Count201207.xls", "Species Count2013-01-15.xls")

gsub("[A-z \\.\\(\\)]", "", x)

[1] "2011-12-15-07-09-39" "0511"                "151112"             
[4] "1011"                "2012-01"             "201207"             
[7] "2013-01-15"         
于 2013-08-06T13:33:20.463 回答
2

如果您担心速度,可以使用sub反向引用来提取您想要的部分。另请注意,这perl=TRUE通常更快(根据?grep)。

jj <- function() sub("[^0-9]*([0-9].*[0-9])[^0-9]*", "\\1", tt, perl=TRUE)
aa <- function() regmatches(tt, regexpr("[0-9].*[0-9]", tt, perl=TRUE))

# Run on R-2.15.2 on 32-bit Windows
microbenchmark(arun <- aa(), josh <- jj(), times=25)
# Unit: milliseconds
#           expr       min        lq    median        uq       max
# 1 arun <- aa() 2156.5024 2189.5168 2191.9972 2195.4176 2410.3255
# 2 josh <- jj()  390.0142  390.8956  391.6431  394.5439  493.2545
identical(arun, josh)  # TRUE

# Run on R-3.0.1 on 64-bit Ubuntu
microbenchmark(arun <- aa(), josh <- jj(), times=25)
# Unit: seconds
#          expr      min       lq   median       uq      max neval
#  arun <- aa() 1.794522 1.839044 1.858556 1.894946 2.207016    25
#  josh <- jj() 1.003365 1.008424 1.009742 1.059129 1.074057    25
identical(arun, josh)  # still TRUE
于 2013-08-06T17:36:21.240 回答
1

使用stringr包提取所有只有数字或数字后跟的字符串-

library(stringr)
str_extract(ll,'([0-9]|[0-9][-])+')

[1] "2011-12-15-07-09-39" "0511"               
    "151112"              "1011"                "2012-01"            
[6] "201207"              "2013-01-15"         
于 2013-08-06T13:35:41.423 回答