[英]Extract maximum number from a text string
I want to extract the highest numeric value from each string considering that sometimes that string will be an NA, which will be copied as NA.我想从每个字符串中提取最高数值,考虑到有时该字符串将是一个 NA,它将被复制为 NA。
I've tried the following solution:我尝试了以下解决方案:
df2$val = sapply(strsplit(df2$NomNivelComplej , '\\D+'), function(x) max(as.numeric(x)))
But all I get is NA但我得到的只是不适用
Data数据
df2 = structure(list(IdCx = c(47111L, 47111L, 47111L, 47111L, 47108L,
47108L, 47107L, 47107L, 47106L, 47106L), NomNivelComplej = c("De 111 Hasta 130 U.V.R.",
NA, "De 111 Hasta 130 U.V.R.", "De 111 Hasta 130 U.V.R.", "De 91 Hasta 100 U.V.R.",
"De 131 Hasta 150 U.V.R.", "De 31 Hasta 40 U.V.R.", "De 71 Hasta 80 U.V.R.",
"De 111 Hasta 130 U.V.R.", "De 111 Hasta 130 U.V.R.")), row.names = c(NA,
10L), class = "data.frame")
A dplyr
and stringr
solution that doesn't assume anything about what the string inside the column is: dplyr
和stringr
解决方案不假设列内的字符串是什么:
library(stringr)
library(dplyr)
get_max = function(x) {
vals = unlist(str_split(x, "\\D"))
max(as.numeric(vals[vals != ""]))
}
df2 %>% rowwise() %>% mutate(max_val = get_max(NomNivelComplej))
# A tibble: 10 × 3
# Rowwise:
IdCx NomNivelComplej max_val
<int> <chr> <dbl>
1 47111 De 111 Hasta 130 U.V.R. 130
2 47111 NA NA
3 47111 De 111 Hasta 130 U.V.R. 130
4 47111 De 111 Hasta 130 U.V.R. 130
5 47108 De 91 Hasta 100 U.V.R. 100
6 47108 De 131 Hasta 150 U.V.R. 150
7 47107 De 31 Hasta 40 U.V.R. 40
8 47107 De 71 Hasta 80 U.V.R. 80
9 47106 De 111 Hasta 130 U.V.R. 130
10 47106 De 111 Hasta 130 U.V.R. 130
You could adapt all `length<-`
's to 3
, calculate the colMaxs
(using matrixStats
package) and replace
if is.infinite
with NA
.您可以将所有
`length<-`
调整为3
,计算colMaxs
(使用matrixStats
包)并将 if is.infinite
replace
为NA
。
df2$val <- df2$NomNivelComplej |>
strsplit('\\D+') |>
sapply(`length<-`, 3) |>
type.convert(as.is=TRUE) |>
matrixStats::colMaxs(na.rm=TRUE) |>
(\(.) replace(., is.infinite(.), NA))()
df2
# IdCx NomNivelComplej val
# 1 47111 De 111 Hasta 130 U.V.R. 130
# 2 47111 <NA> NA
# 3 47111 De 111 Hasta 130 U.V.R. 130
# 4 47111 De 111 Hasta 130 U.V.R. 130
# 5 47108 De 91 Hasta 100 U.V.R. 100
# 6 47108 De 131 Hasta 150 U.V.R. 150
# 7 47107 De 31 Hasta 40 U.V.R. 40
# 8 47107 De 71 Hasta 80 U.V.R. 80
# 9 47106 De 111 Hasta 130 U.V.R. 130
# 10 47106 De 111 Hasta 130 U.V.R. 130
Note: R >= 4.1 used注意:使用 R >= 4.1
Data:数据:
df2 <- structure(list(IdCx = c(47111L, 47111L, 47111L, 47111L, 47108L,
47108L, 47107L, 47107L, 47106L, 47106L), NomNivelComplej = c("De 111 Hasta 130 U.V.R.",
NA, "De 111 Hasta 130 U.V.R.", "De 111 Hasta 130 U.V.R.", "De 91 Hasta 100 U.V.R.",
"De 131 Hasta 150 U.V.R.", "De 31 Hasta 40 U.V.R.", "De 71 Hasta 80 U.V.R.",
"De 111 Hasta 130 U.V.R.", "De 111 Hasta 130 U.V.R.")), row.names = c(NA,
10L), class = "data.frame")
You could do as follows:您可以执行以下操作:
temp <- c()
for (i in df2$NomNivelComplej) {
j <- max(as.numeric(unlist(regmatches(i, gregexpr("[[:digit:]]+", i)))), na.rm = T)
temp <- c(temp, j)
}
df2 <- cbind(df2, temp)
Output: Output:
IdCx NomNivelComplej temp
1 47111 De 111 Hasta 130 U.V.R. 130
2 47111 <NA> -Inf
3 47111 De 111 Hasta 130 U.V.R. 130
4 47111 De 111 Hasta 130 U.V.R. 130
5 47108 De 91 Hasta 100 U.V.R. 100
6 47108 De 131 Hasta 150 U.V.R. 150
7 47107 De 31 Hasta 40 U.V.R. 40
8 47107 De 71 Hasta 80 U.V.R. 80
9 47106 De 111 Hasta 130 U.V.R. 130
10 47106 De 111 Hasta 130 U.V.R. 130
Note: It returns -Inf
in the case of NA
.注意:它在
NA
的情况下返回-Inf
。 But, you can always take care of it.但是,你总是可以照顾它。
Just add na.rm = T
to your max
function, and then replace infinite values with NA
.只需将
na.rm = T
添加到您的max
function,然后用NA
替换无限值。
df2$val <- sapply(strsplit(df2$NomNivelComplej , '\\D+'), function(x) max(as.integer(x), na.rm = T))
df2$val <- replace(df2$val, is.infinite(df2$val), NA)
You could also use a built-in function (taken from here ).您还可以使用内置的 function(取自此处)。
mymax <- function(x) ifelse( !all(is.na(x)), max(x, na.rm=T), NA)
df2$val <- sapply(strsplit(df2$NomNivelComplej , '\\D+'), function(x) mymax(as.integer(x)))
Output: Output:
# > df2
# IdCx NomNivelComplej val
# 1 47111 De 111 Hasta 130 U.V.R. 130
# 2 47111 <NA> NA
# 3 47111 De 111 Hasta 130 U.V.R. 130
# 4 47111 De 111 Hasta 130 U.V.R. 130
# 5 47108 De 91 Hasta 100 U.V.R. 100
# 6 47108 De 131 Hasta 150 U.V.R. 150
# 7 47107 De 31 Hasta 40 U.V.R. 40
# 8 47107 De 71 Hasta 80 U.V.R. 80
# 9 47106 De 111 Hasta 130 U.V.R. 130
# 10 47106 De 111 Hasta 130 U.V.R. 130
You can capitalize on the fact that the string-highest value always follows "Hasta ":您可以利用字符串最高值始终遵循“Hasta”这一事实:
library(stringr)
library(dplyr)
df2 %>%
mutate(max = str_extract(NomNivelComplej, "(?<=Hasta )\\d+"))
IdCx NomNivelComplej max
1 47111 De 111 Hasta 130 U.V.R. 130
2 47111 <NA> <NA>
3 47111 De 111 Hasta 130 U.V.R. 130
4 47111 De 111 Hasta 130 U.V.R. 130
5 47108 De 91 Hasta 100 U.V.R. 100
6 47108 De 131 Hasta 150 U.V.R. 150
7 47107 De 31 Hasta 40 U.V.R. 40
8 47107 De 71 Hasta 80 U.V.R. 80
9 47106 De 111 Hasta 130 U.V.R. 130
10 47106 De 111 Hasta 130 U.V.R. 130
In base R
:在
base R
:
library(stringr)
df2$max <- str_extract(df2$NomNivelComplej, "(?<=Hasta )\\d+")
An option with base R
带有
base R
的选项
df2$Max <- do.call(pmax, read.csv(text = trimws(gsub("\\D+", ",",
df2$NomNivelComplej), whitespace = ","), header = FALSE))
-output -输出
> df2
IdCx NomNivelComplej Max
1 47111 De 111 Hasta 130 U.V.R. 130
2 47111 <NA> NA
3 47111 De 111 Hasta 130 U.V.R. 130
4 47111 De 111 Hasta 130 U.V.R. 130
5 47108 De 91 Hasta 100 U.V.R. 100
6 47108 De 131 Hasta 150 U.V.R. 150
7 47107 De 31 Hasta 40 U.V.R. 40
8 47107 De 71 Hasta 80 U.V.R. 80
9 47106 De 111 Hasta 130 U.V.R. 130
10 47106 De 111 Hasta 130 U.V.R. 130
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.