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

Extract maximum number from a text string

我想从每个字符串中提取最大的数值,考虑到有时该字符串将是 NA,它将被复制为 NA。

我尝试了以下解决方案:

df2$val = sapply(strsplit(df2$NomNivelComplej , '\D+'), function(x) max(as.numeric(x)))

但我得到的只是 NA

数据

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")

您可以将所有 `length<-` 调整为 3,计算 colMaxs(使用 matrixStats 包)和 replace 如果 is.infiniteNA.

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

注意: R >= 4.1 使用


数据:

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")

您可以进行如下操作:

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)

输出:

    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

注:在NA的情况下是returns-Inf。但是,你总是可以照顾它。

只需将 na.rm = T 添加到您的 max 函数中,然后将无限值替换为 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)

您也可以使用内置函数(取自 here)。

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)))

输出:

# > 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

您可以利用以下事实:字符串最高值始终跟在“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

base R中:

library(stringr)
df2$max <- str_extract(df2$NomNivelComplej, "(?<=Hasta )\d+")

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

选项base R

df2$Max <-  do.call(pmax, read.csv(text = trimws(gsub("\D+", ",", 
     df2$NomNivelComplej), whitespace = ","), header = FALSE))

-输出

> 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