Тест для числовых элементов в символьной строке
Я хочу проверить строку символов и посмотреть, какие элементы могут быть действительно числовыми. Я могу использовать регулярное выражение для проверки успешного целого числа, но я хочу посмотреть, какие элементы имеют все цифры и 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 wrong but don't know what to do
Я ищу логический вывод, поэтому ожидаю следующих результатов:
[1] TRUE TRUE TRUE TRUE FALSE FALSE
Ответы
Ответ 1
Возможно, есть причина, по которой некоторые другие части ваших данных более сложны, и это может сломать это, но моя первая мысль:
> !is.na(as.numeric(x))
[1] TRUE TRUE TRUE TRUE FALSE FALSE
Как указано ниже Джошем О'Брайеном, это не будет воспринимать такие вещи, как 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
... и затем разделите "L" только на те элементы, используя gsub
и индексирование.
Ответ 2
Недавно я столкнулся с аналогичной проблемой, когда я пытался написать функцию для форматирования значений, передаваемых в виде символьной строки из другой функции. Отформатированные значения в конечном итоге окажутся в таблице, и я хотел бы создать логику для идентификации 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) OR
- положительные или отрицательные числа в научной нотации
Дополнительные термины могут быть добавлены для обработки десятичных знаков без предшествующей цифры или цифр с десятичной точкой, но не цифр после десятичной, если набор данных содержит числа в плохом виде.
Ответ 3
Вдохновленные ответами здесь, моя функция обрезает начальные и конечные пробелы, может обрабатывать 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))
}
Ответ 4
Вы также можете использовать:
readr::parse_number("I am 4526dfkljvdljkvvkv")
Чтобы получить 4526.