web-dev-qa-db-fra.com

Test des éléments numériques dans une chaîne de caractères

Je veux tester une chaîne de caractères et voir quels éléments pourraient être numériques. Je peux utiliser l'expression régulière pour tester la réussite de l'entier, mais je cherche à voir quels éléments ont tous les chiffres et 1 décimales ou moins. Voici ce que j'ai essayé:

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

Je recherche une sortie logique, je m'attends donc aux résultats suivants:

[1] TRUE TRUE TRUE TRUE FALSE FALSE
39
Tyler Rinker

Peut-être y a-t-il une raison pour laquelle d'autres éléments de vos données sont plus compliqués qui pourraient casser cela, mais ma première pensée est:

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

Comme indiqué ci-dessous par Josh O'Brien, cela ne ramassera pas des choses comme 7L, que l'interpréteur R analyserait comme l'entier 7. Si vous aviez besoin de les inclure comme "numériquement plausibles", une route serait de les sélectionner d'abord avec une expression régulière,

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

... puis supprimez le "L" de ces éléments en utilisant gsub et l'indexation.

51
joran

J'ai récemment rencontré un problème similaire où j'essayais d'écrire une fonction pour formater les valeurs passées en tant que chaîne de caractères d'une autre fonction. Les valeurs formatées se retrouveraient finalement dans un tableau et je voulais créer une logique pour identifier NA, les chaînes de caractères et les représentations de caractères des nombres afin de pouvoir leur appliquer sprintf() avant de générer le tableau.

Bien que plus compliqué à lire, j'aime la robustesse de l'approche grepl(). Je pense que cela reprend tous les exemples mentionnés dans les commentaires.

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)

Cela serait évalué à (formaté pour aider à la visualisation):

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

L'expression régulière est VRAIE pour:

  • nombres positifs ou négatifs avec pas plus d'une décimale OU
  • entiers positifs ou négatifs (par exemple, 4L) OU
  • nombres positifs ou négatifs en notation scientifique

Des termes supplémentaires pourraient être ajoutés pour gérer les décimales sans premier chiffre ou les nombres avec un point décimal mais pas les chiffres après la décimale si l'ensemble de données contenait des nombres sous une forme médiocre.

5
penguinv22

Évitez de réinventer la roue avec check.numeric() du package varhandle .

La fonction accepte les arguments suivants:

v Le vecteur caractère ou vecteur facteur. (Obligatoire)

na.rm logique. La fonction doit-elle ignorer NA? La valeur par défaut est FLASE car NA peut être converti en numérique. (Optionnel)

only.integer logique. Vérifiez uniquement les nombres entiers et n'acceptez pas les virgules flottantes. La valeur par défaut est FALSE. (Optionnel)

exceptions Vecteur de caractères contenant les chaînes qui doivent être considérées comme valides pour être converties en numérique. (Optionnel)

ignore.whitespace logique. Ignorez les caractères d'espacement avant et arrière avant d'évaluer si le vecteur peut être converti en numérique. La valeur par défaut est TRUE. (Optionnel)

1
qwr

Vous pouvez aussi utiliser:

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

Pour obtenir 4526.

0
SteveS

Inspirée par les réponses ici, ma fonction ajuste les espaces blancs de début et de fin, peut gérer na.strings et traite éventuellement NA comme numérique. L'expression régulière a également été améliorée. Voir les informations d'aide pour plus de détails. Tout ce que tu veux!

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))
}
0
Jerry T