使用 gsub() 从 R 中的数组中提取数字

Using gsub() to extract numbers from an array in R

我想从以下数组中删除 &. 并仅提取数字,

x = as.factor(c(".&.", "0.0119885482338&.&.", ".&2.25880593895", ".&.&.&.&.&.&.&.", ".&0.295142083575&.", "0.708323350364",".&.&0.193766679861",".&.&.&.&7.65239874523E-4&.&."))

我尝试了以下 gsub() 命令:

gsub("[^0-9.E-]","",x)

输出:

".."                     "0.0119885482338.."      ".2.25880593895"         
"........"              
".0.295142083575."       "0.708323350364"         "..0.193766679861"       
"....7.65239874523E-4.." 

更新上述 gsub 命令的任何建议,以便输出如下所示:

"" "0.0119885482338" "2.25880593895" "" "0.295142083575" 
"0.708323350364" "0.193766679861" "7.65239874523E-4"  

您可以使用

> sub("^.*?(?:([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?).*|$)","\1",x)
[1] ""                 "0.0119885482338"  "2.25880593895"    ""                 "0.295142083575"   "0.708323350364"   "0.193766679861"   "7.65239874523E-4"

参见regex demo

详情:

  • ^ - 字符串开头
  • .*? - 任何文本,尽可能短
  • (?: - 非捕获组的开始:
    • ([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?) - 第 1 组 (</code>):一个 <a href="">number pattern</a></li> <li><code>.* - 字符串的其余部分
  • |
    • $ - 字符串结尾
  • ) - 非捕获组结束。

看到一个 online R demo:

x=as.factor(c(".&.", "0.0119885482338&.&.", ".&2.25880593895", ".&.&.&.&.&.&.&.", ".&0.295142083575&.", "0.708323350364",".&.&0.193766679861",".&.&.&.&7.65239874523E-4&.&."))
sub("^.*?(?:([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?).*|$)","\1",x)
## => [1] ""                 "0.0119885482338"  "2.25880593895"    ""                
##    [5] "0.295142083575"   "0.708323350364"   "0.193766679861"   "7.65239874523E-4"

这是使用 grepl 后跟 sub 的基础 R 方法:

x <- x[grepl("\d+", x)]
x <- sub("^.*?(\d+(?:\.\d+)?(?:E[-+]\d+)?).*$", "\1", x)
x

[1] "0.0119885482338"  "2.25880593895"    "0.295142083575"   "0.708323350364"  
[5] "0.193766679861"   "7.65239874523E-4"

如果您希望结果是字符,请在下面的备选方案中删除末尾的 as.numeric。

1)以下不使用正则表达式。问题中显示的输入形式是 & 分隔字段,因此它将 x 从因子转换为字符,将其拆分为由 & 分隔的字段,单独删除字段中的任何点,然后将余数转换为数字。没有使用包。

s <- unlist(strsplit(paste(x), "&", fixed = TRUE))
as.numeric(s[s != "."])
## [1] 0.0119885482 2.2588059390 0.2951420836 0.7083233504 0.1937666799
## [6] 0.0007652399

或者,我们可以将其表示为管道

library(magrittr)

x %>%
  paste %>%
  strsplit("&", fixed = TRUE) %>%
  unlist %>%
  Filter(function(x) x != ".", .) %>%
  as.numeric
## [1] 0.0119885482 2.2588059390 0.2951420836 0.7083233504 0.1937666799
## [6] 0.0007652399

2) 如果我们之后删除前导点和尾随点,删除零长度字段并转换为数字

,问题中的方法就可以工作
as.numeric(Filter(nzchar, trimws(gsub("[^0-9.E-]","",x),, whitespace = "\.")))
## [1] 0.0119885482 2.2588059390 0.2951420836 0.7083233504 0.1937666799
## [6] 0.0007652399

更新

评论中提到希望结果与输入的长度相同。假设在那种情况下我们想要字符输出,我们可以将上面的内容缩短为以下内容:

L <- strsplit(paste(x), "&", fixed = TRUE)
sapply(L, function(x) c(x[x != "."], "")[1])
## [1] ""                 "0.0119885482338"  "2.25880593895"    ""                
## [5] "0.295142083575"   "0.708323350364"   "0.193766679861"   "7.65239874523E-4"

x %>% paste %>% strsplit("&", fixed = TRUE) %>% sapply(function(x) c(x[x != "."], "")[1])
## [1] ""                 "0.0119885482338"  "2.25880593895"    ""                
## [5] "0.295142083575"   "0.708323350364"   "0.193766679861"   "7.65239874523E-4"


trimws(gsub("[^0-9.E-]","",x), whitespace = "\.")
## [1] ""                 "0.0119885482338"  "2.25880593895"    ""                
## [5] "0.295142083575"   "0.708323350364"   "0.193766679861"   "7.65239874523E-4"

如果 .& 总是在一起(在您给出的示例中就是这种情况),您可以使用 \.*&\.*.

gsub("\.*&\.*", "", x)
#[1] ""                 "0.0119885482338"  "2.25880593895"    ""                
#[5] "0.295142083575"   "0.708323350364"   "0.193766679861"   "7.65239874523E-4"