58

我想测试一个字符串,看看哪些元素实际上可能是数字。我可以使用正则表达式来测试整数是否成功,但我希望查看哪些元素具有所有数字和 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
4

6 回答 6

72

也许有一些其他数据更复杂的原因会破坏这一点,但我的第一个想法是:

> !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”。

于 2012-11-30T03:01:33.167 回答
8

我最近遇到了一个类似的问题,我试图编写一个函数来格式化从另一个函数作为字符串传递的值。格式化的值最终会出现在一个表格中,我想创建逻辑来识别 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)或
  • 科学计数法中的正数或负数

如果数据集包含格式不佳的数字,则可以添加其他术语来处理没有前导数字的小数或带有小数点但小数点后没有数字的数字。

于 2014-01-16T06:14:58.760 回答
1

check.numeric()避免使用from package varhandle重新发明轮子。

该函数接受以下参数:

v字符向量或因子向量。(强制的)

na.rm合乎逻辑。该函数是否应该忽略 NA?默认值为 FLASE,因为 NA 可以转换为数字。(选修的)

only.integer逻辑。只检查整数,不接受浮点数。默认值为假。(选修的)

异常包含字符串的字符向量,这些字符串应被视为有效转换为数字。(选修的)

ignore.whitespace逻辑。在评估向量是否可以转换为数字之前,请忽略前导和尾随空白字符。默认值为 TRUE。(选修的)

于 2019-08-01T02:01:38.870 回答
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"
于 2020-03-24T16:20:53.817 回答
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))
}
于 2018-11-13T01:30:46.037 回答
-2

您还可以使用:

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

得到4526。

于 2019-05-23T09:32:20.327 回答