从 R 中具有多个数字的字符串中提取给定符号后的第一个数字(带小数点)
Extract the first number (with decimals) after a given symbol from a string with multiple numbers in R
我正在尝试从字符串中获取数字(包括小数)。
我的数据是这样的:
V <- c("7.20-<7.35","25-<32","60-<83e","40-<50","0.85-<1.15","80-<98","3.0-<3.4","NA","3.0-<3.4 (110)")
其中数字与字母和符号混合。
我需要提取 < 符号后的第一个数字,同时保留缺失值的索引。
我的输出看起来像:
desired.output <- c(7.35, 32, 83, 50, 1.15, 98, 3.4, NA, 3.4)
我试过:
resp <- as.numeric(unlist(regmatches(V,
gregexpr("[[:digit:]]+\.*[[:digit:]]*",V))))
和
resp <- sub(".*<(^[^-])", "\1", V)
子函数中还有另一个模式,但似乎没有任何效果。
您认为最好的方法是什么?
您可以使用
sub(".*<(\d+(?:\.\d+)?).*", "\1", V, perl=TRUE)
# => [1] "7.35" "32" "83" "50" "1.15" "98" "3.4" "NA" "3.4"
见online R demo and the regex demo。如果您还需要获得像 .05
这样的数字,请将 \d+(?:\.\d+)?
替换为 \d*\.?\d+
。如果您还需要获得负数,请在第一个 \d+
之前附加 -?
。
详情:
.*
- 除换行字符外的任何零个或多个字符,尽可能多
<
- 一个 <
字符
(\d+(?:\.\d+)?)
- 第 1 组(从替换模式中引用 </code>):一位或多位数字后跟可选的点序列和一位或多位数字</li>
<li><code>.*
- 除换行字符外的任何零个或多个字符,尽可能多
您还可以指定第一个数字,后跟 -<
并使用可选的小数捕获第二部分。
\d+(?:\.\d+)?-<(\d+(?:\.\d+)?).*
模式匹配:
\d+(?:\.\d+)?
匹配 1+ 个带可选小数部分的数字
-<
字面匹配
(
捕获 组 1
\d+(?:\.\d+)?
匹配 1+ 个带可选小数部分的数字
)
关闭组 1
.*
匹配行的其余部分
然后你可以匹配结果中不需要的字符串的其余部分,并替换为第1组。
V <- c("7.20-<7.35","25-<32","60-<83e","40-<50","0.85-<1.15","80-<98","3.0-<3.4","NA","3.0-<3.4 (110)")
sub("\d+(?:\.\d+)?-<(\d+(?:\.\d+)?).*", "\1", V)
输出
[1] "7.35" "32" "83" "50" "1.15" "98" "3.4" "NA" "3.4"
匹配 -
<
或 >
的所有变体,您可以使用字符 class 列出所有允许的字符并重复它们 1 次或多次:
sub("\d+(?:\.\d+)?[<>-]+(\d+(?:\.\d+)?).*", "\1", V)
使用 tidyverse 中 stringr
包中的 str_extract
:
library(tidyverse)
V <- c("7.20-<7.35","25-<32","60-<83e","40-<50","0.85-<1.15","80-<98","3.0-<3.4","NA","3.0-<3.4 (110)")
str_extract(V, "((?<=\<)\d\.?\d+|NA)") %>%
as.numeric()
[1] 7.35 32.00 83.00 50.00 1.15 98.00 3.40 NA 3.40
我正在尝试从字符串中获取数字(包括小数)。 我的数据是这样的:
V <- c("7.20-<7.35","25-<32","60-<83e","40-<50","0.85-<1.15","80-<98","3.0-<3.4","NA","3.0-<3.4 (110)")
其中数字与字母和符号混合。 我需要提取 < 符号后的第一个数字,同时保留缺失值的索引。 我的输出看起来像:
desired.output <- c(7.35, 32, 83, 50, 1.15, 98, 3.4, NA, 3.4)
我试过:
resp <- as.numeric(unlist(regmatches(V,
gregexpr("[[:digit:]]+\.*[[:digit:]]*",V))))
和
resp <- sub(".*<(^[^-])", "\1", V)
子函数中还有另一个模式,但似乎没有任何效果。
您认为最好的方法是什么?
您可以使用
sub(".*<(\d+(?:\.\d+)?).*", "\1", V, perl=TRUE)
# => [1] "7.35" "32" "83" "50" "1.15" "98" "3.4" "NA" "3.4"
见online R demo and the regex demo。如果您还需要获得像 .05
这样的数字,请将 \d+(?:\.\d+)?
替换为 \d*\.?\d+
。如果您还需要获得负数,请在第一个 \d+
之前附加 -?
。
详情:
.*
- 除换行字符外的任何零个或多个字符,尽可能多<
- 一个<
字符(\d+(?:\.\d+)?)
- 第 1 组(从替换模式中引用</code>):一位或多位数字后跟可选的点序列和一位或多位数字</li> <li><code>.*
- 除换行字符外的任何零个或多个字符,尽可能多
您还可以指定第一个数字,后跟 -<
并使用可选的小数捕获第二部分。
\d+(?:\.\d+)?-<(\d+(?:\.\d+)?).*
模式匹配:
\d+(?:\.\d+)?
匹配 1+ 个带可选小数部分的数字-<
字面匹配(
捕获 组 1\d+(?:\.\d+)?
匹配 1+ 个带可选小数部分的数字
)
关闭组 1.*
匹配行的其余部分
然后你可以匹配结果中不需要的字符串的其余部分,并替换为第1组。
V <- c("7.20-<7.35","25-<32","60-<83e","40-<50","0.85-<1.15","80-<98","3.0-<3.4","NA","3.0-<3.4 (110)")
sub("\d+(?:\.\d+)?-<(\d+(?:\.\d+)?).*", "\1", V)
输出
[1] "7.35" "32" "83" "50" "1.15" "98" "3.4" "NA" "3.4"
匹配 -
<
或 >
的所有变体,您可以使用字符 class 列出所有允许的字符并重复它们 1 次或多次:
sub("\d+(?:\.\d+)?[<>-]+(\d+(?:\.\d+)?).*", "\1", V)
使用 tidyverse 中 stringr
包中的 str_extract
:
library(tidyverse)
V <- c("7.20-<7.35","25-<32","60-<83e","40-<50","0.85-<1.15","80-<98","3.0-<3.4","NA","3.0-<3.4 (110)")
str_extract(V, "((?<=\<)\d\.?\d+|NA)") %>%
as.numeric()
[1] 7.35 32.00 83.00 50.00 1.15 98.00 3.40 NA 3.40