测试字符串中的数字元素

时间:2012-11-30 02:58:12

标签: regex r

我想测试一个字符串,看看哪些元素实际上可以是数字。我可以使用正则表达式来测试整数是否成功,但我希望看到哪些元素具有所有数字和1或更少的小数。以下是我的尝试:

x <- c("0.33", ".1", "3", "123", "2.3.3", "1.2r")
!grepl("[^0-9]", x)   #integer test

grepl("[^0-9[\\.{0,1}]]", x)  # I know it's wrong but don't know what to do

我正在寻找逻辑输出,所以我希望得到以下结果:

[1] TRUE TRUE TRUE TRUE FALSE FALSE

6 个答案:

答案 0 :(得分:49)

也许有一个原因是你的数据的其他部分更复杂,会打破这个,但我的第一个想法是:

> !is.na(as.numeric(x))
[1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE

如下面Josh O'Brien所说,这不会选择像7L这样的东西,R解释器会将其解析为整数7.如果你需要将那些包含为“合理数字”,那么一条路线就会首先用正则表达式来挑选它们,

x <- c("1.2","1e4","1.2.3","5L")
> x
[1] "1.2"   "1e4"   "1.2.3" "5L"   
> grepl("^[[:digit:]]+L",x)
[1] FALSE FALSE FALSE  TRUE

...然后使用gsub和索引从这些元素中剥离“L”。

答案 1 :(得分:5)

我最近遇到了类似的问题,我试图编写一个函数来格式化从另一个函数作为字符串传递的值。格式化的值最终会在表格中结束,我想创建逻辑来识别数字的NA,字符串和字符表示,以便在生成表格之前可以对它们应用sprintf()

虽然读起来比较复杂,但我确实喜欢grepl()方法的稳健性。我认为这会得到评论中提到的所有例子。

x <- c("0",37,"42","-5","-2.3","1.36e4","4L","La","ti","da",NA)

y <- grepl("[-]?[0-9]+[.]?[0-9]*|[-]?[0-9]+[L]?|[-]?[0-9]+[.]?[0-9]*[eE][0-9]+",x)

这将被评估为(格式化以帮助可视化):

x
[1] "0"  "37"   "42"  "-5"   "-2.3"   "1.36e4" "4L" "La"     "ti"     "da"     NA 

y
[1] TRUE  TRUE   TRUE  TRUE   TRUE     TRUE    TRUE FALSE   FALSE    FALSE    FALSE

正则表达式为TRUE:

  • 正数或负数,不超过一位小数或
  • 正整数或负整数(例如,4L)或
  • 科学记数法中的正数或负数

如果数据集包含数字不佳的数字,可以添加附加条款来处理没有前导数字的小数或带小数点的数字但不包括小数点后的数字。

答案 2 :(得分:1)

避免使用{strong> varhandle 软件包中的check.numeric()重新发明轮子。

该函数接受以下参数:

  

v 字符向量或因子向量。 (必填)

     

na.rm 符合逻辑。该函数应该忽略NA吗?默认值为FLASE   因为NA可以转换为数字。 (可选)

     

only.integer 符合逻辑。仅检查整数,不接受   浮点。默认值为FALSE。 (可选)

     

例外一个字符向量,其中包含应该为   视为有效,可以转换为数字。 (可选)

     

ignore.whitespace 符合逻辑。忽略前导和尾随空格   字符,然后评估向量是否可以转换为数字。   默认值为TRUE。 (可选)

答案 3 :(得分:1)

另一种可能性:

x <- c("0.33", ".1", "3", "123", "2.3.3", "1.2r", "1.2", "1e4", "1.2.3", "5L", ".22", -3)
locs <- sapply(x, function(n) {

    out <- try(eval(parse(text = n)), silent = TRUE)
    !inherits(out, 'try-error')

}, USE.NAMES = FALSE)

x[locs]
## [1] "0.33" ".1"   "3"    "123"  "1.2"  "1e4"  "5L"   ".22"  "-3"  

x[!locs]
## [1] "2.3.3" "1.2r"  "1.2.3"

答案 4 :(得分:0)

受此处答案的启发,我的函数修剪了开头和结尾的空格,可以处理na.strings,也可以选择将NA视为数字。正则表达式也得到增强。有关详细信息,请参见帮助信息。所有你想要的!

check if a str obj is actually numeric
@description check if a str obj is actually numeric
#' @param x a str vector, or a factor of str vector, or numeric vector. x will be coerced and trimws.
#' @param na.strings case sensitive strings that will be treated to NA.
#' @param naAsTrue whether NA (including actual NA and na.strings) will be treated as numeric like
#' @return a logical vector (vectorized).
#' @export
#' @note Using regular expression
#' \cr TRUE for any actual numeric c(3,4,5,9.9) or c("-3","+4.4",   "-42","4L","9L",   "1.36e4","1.36E4",    NA, "NA", "","NaN", NaN): 
#' \cr positive or negative numbers with no more than one decimal c("-3","+4.4") OR
#' \cr positive or negative integers (e.g., c("-42","4L","39L")) OR
#' \cr positive or negative numbers in scientific notation c("1.36e4","1.36E4")
#' \cr NA, or na.strings
is.numeric.like <- function(x,naAsTrue=TRUE,na.strings=c('','.','NA','na','N/A','n/a','NaN','nan')){
    x = trimws(x,'both')
    x[x %in% na.strings] = NA
    # https://stackoverflow.com/a/21154566/2292993
    result = grepl("^[\\-\\+]?[0-9]+[\\.]?[0-9]*$|^[\\-\\+]?[0-9]+[L]?$|^[\\-\\+]?[0-9]+[\\.]?[0-9]*[eE][0-9]+$",x,perl=TRUE)
    if (naAsTrue) result = result | is.na(x)
    return((result))
}

答案 5 :(得分:0)

您还可以使用:

readr::parse_number("I am 4526dfkljvdljkvvkv")

得到4526。