web-dev-qa-db-fra.com

Extraire des nombres uniques de la chaîne en R

J'ai une liste de chaînes qui contiennent des caractères aléatoires tels que:

list=list()
list[1] = "djud7+dg[a]hs667"
list[2] = "7fd*hac11(5)"
list[3] = "2tu,g7gka5"

Je voudrais savoir quels numéros sont présents au moins une fois (unique()) dans cette liste. La solution de mon exemple est:

solution: c(7,667,11,5,2)

Si quelqu'un a une méthode qui ne considère pas 11 comme "onze" mais comme "un et un", cela serait également utile. La solution dans cette condition serait:

solution: c(7,6,1,5,2)

(J'ai trouvé cet article sur un sujet connexe: Extraction de nombres à partir de vecteurs de chaînes )

29
Remi.b

Pour la deuxième réponse, vous pouvez utiliser gsub pour supprimer tout de la chaîne qui n'est pas un nombre, puis diviser la chaîne comme suit:

unique(as.numeric(unlist(strsplit(gsub("[^0-9]", "", unlist(ll)), ""))))
# [1] 7 6 1 5 2

Pour la première réponse, en utilisant de manière similaire strsplit,

unique(na.omit(as.numeric(unlist(strsplit(unlist(ll), "[^0-9]+")))))
# [1]   7 667  11   5   2

PS: ne nommez pas votre variable list (car il y a une fonction intégrée list). J'ai nommé vos données comme ll.

56
Arun

Voici encore une autre réponse, celle-ci utilisant gregexpr pour trouver les nombres, et regmatches pour les extraire:

l <- c("djud7+dg[a]hs667", "7fd*hac11(5)", "2tu,g7gka5")

temp1 <- gregexpr("[0-9]", l)   # Individual digits
temp2 <- gregexpr("[0-9]+", l)  # Numbers with any number of digits

as.numeric(unique(unlist(regmatches(l, temp1))))
# [1] 7 6 1 5 2
as.numeric(unique(unlist(regmatches(l, temp2))))
# [1]   7 667  11   5   2
16

Une solution utilisant stringi

 # extract the numbers:

 nums <- stri_extract_all_regex(list, "[0-9]+")

 # Make vector and get unique numbers:

 nums <- unlist(nums)
 nums <- unique(nums)

Et c'est votre première solution

Screenshot from on-liner in R

Pour la deuxième solution, j'utiliserais substr:

nums_first <- sapply(nums, function(x) unique(substr(x,1,1)))
7
altabq

Vous pouvez utiliser ?strsplit (comme suggéré dans la réponse de @ Arun dans Extraction de nombres à partir de vecteurs (de chaînes) ):

l <- c("djud7+dg[a]hs667", "7fd*hac11(5)", "2tu,g7gka5")

## split string at non-digits
s <- strsplit(l, "[^[:digit:]]")

## convert strings to numeric ("" become NA)
solution <- as.numeric(unlist(s))

## remove NA and duplicates
solution <- unique(solution[!is.na(solution)])
# [1]   7 667  11   5   2
6
sgibb

Une solution stringr avec str_match_all et les opérateurs canalisés. Pour la première solution:

library(stringr)
str_match_all(ll, "[0-9]+") %>% unlist %>% unique %>% as.numeric

Deuxième solution:

str_match_all(ll, "[0-9]") %>% unlist %>% unique %>% as.numeric

(Remarque: j'ai également appelé la liste ll)

4
Joe

Découvrez la fonction str_extract_numbers() du package strex.

pacman::p_load(strex)
list=list()
list[1] = "djud7+dg[a]hs667"
list[2] = "7fd*hac11(5)"
list[3] = "2tu,g7gka5"
charvec <- unlist(list)
print(charvec)
#> [1] "djud7+dg[a]hs667" "7fd*hac11(5)"     "2tu,g7gka5"
str_extract_numbers(charvec)
#> [[1]]
#> [1]   7 667
#> 
#> [[2]]
#> [1]  7 11  5
#> 
#> [[3]]
#> [1] 2 7 5
unique(unlist(str_extract_numbers(charvec)))
#> [1]   7 667  11   5   2

Créé le 2018-09-03 par le package reprex (v0.2.0).

1
Rory Nolan

Utilisez strsplit en utilisant le modèle comme l'inverse des chiffres numériques: 0-9

Pour l'exemple que vous avez fourni, procédez comme suit:

tmp <- sapply(list, function (k) strsplit(k, "[^0-9]"))

Ensuite, prenez simplement une union de tous les "ensembles" dans la liste, comme ceci:

tmp <- Reduce(union, tmp)

Il vous suffit ensuite de supprimer la chaîne vide.

1
asb