从文本字符串中提取最大数字
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.infinite
与 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
注意: 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+")
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
选项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
我想从每个字符串中提取最大的数值,考虑到有时该字符串将是 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.infinite
与 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
注意: 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+")
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
选项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