简体   繁体   English

从文本字符串中提取最大数

[英]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: dplyrstringr解决方案不假设列内的字符串是什么:

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 replaceNA

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM