2013-06-09 3 views
29

У меня есть список строк, содержащих случайные символы, такие как:Извлечение уникальных номеров из строки в R

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

Я хотел бы знать, какие номера присутствуют, по крайней мере один раз (unique()) в этом списке. Решение моего примера:

решение: c(7,667,11,5,2)

Если кто-то есть метод, который не считает 11 как «одиннадцать», а как «один и один», также было бы полезно. Решение в этом состоянии будет:

решение: c(7,6,1,5,2)

(я нашел этот пост на схожую тему: Extracting numbers from vectors of strings)

ответ

54

Для второго ответа, вы можете использовать gsub, чтобы удалить все из строки это не число, а затем разбить строку следующим образом:

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

Для первого ответа, так же с помощью strsplit,

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

PS: не называйте свою переменную list (так как есть встроенная функция list). Я назвал ваши данные ll.

6

Вы можете использовать ?strsplit (как предложено в @ ответ Аруна в Extracting numbers from vectors (of strings)):

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 
1

Использование strsplit с использованием шаблона в виде обратной числовых разрядов: 0-9

Для примера вы предоставили , сделайте следующее:

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

Тогда просто взять объединение всех `устанавливает в списке, например, так:

tmp <- Reduce(union, tmp) 

Тогда вам остается только удалить пустую строку.

+0

Три идентичных ответа в минуту друг друга! : D – asb

+0

'strsplit' векторизован. Вы можете/не должны использовать циклы путем 'unlist'ing данных OP. – Arun

+0

Использование 'Reduce' с' union' (по сути, цикл) здесь также будет очень трудоемким в огромных списках ('unique' и' unlist' будет намного быстрее). – Arun

15

Вот еще один ответ, это один с помощью gregexpr, чтобы найти номера и regmatches извлечь их:

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 
4

stringr решения с str_match_all и водопроводными операторами.Для первого решения:

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

Второе решение:

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

(Примечание: Я также назвал список ll)

7

Раствор с помощью stringi

# extract the numbers: 

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

# Make vector and get unique numbers: 

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

И это ваше первое решение

Screenshot from on-liner in R

Для второго решения я хотел бы использовать substr:

nums_first <- sapply(nums, function(x) unique(substr(x,1,1))) 
+0

Откуда появляется 'stri_extract_all_regex()'? –

+0

Пакет stringi, как говорится в названии – altabq

1

Проверьте свою функцию extract_numbers() из filesstrings пакета. Установите его через install.packages("filesstrings").

library(filesstrings) 
#> Loading required package: stringr 
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" 
extract_numbers(charvec) 
#> [[1]] 
#> [1] 7 667 
#> 
#> [[2]] 
#> [1] 7 11 5 
#> 
#> [[3]] 
#> [1] 2 7 5 
unique(unlist(ExtractNumbers(charvec))) 
#> [1] 7 667 11 5 2 
Смежные вопросы