2015-11-04 3 views
4

Мне нужно разложить около 75 миллионов строк символов, используя R. Мне нужно сделать что-то вроде создания матрицы Term Document, где каждое слово, которое встречается в документе, становится столбцом в матрице и в любом месте этого термина, матричный элемент кодируется как 1.Разложение строки

У меня: Около 75 миллионов строк символов длиной от 0 до 100 символов; они представляют временной ряд, дающий закодированную информацию о том, что произошло в этот период. Каждый код имеет ровно один символ и соответствует периоду времени.

Мне нужно: Какая-то матрица или способ передачи информации, отнимающей временные ряды, и просто говорит мне, сколько раз в каждой серии сообщалось о некотором коде.

Например: Строка «ABCDEFG-123» станет строкой в ​​матрице, где каждый символ будет подсвечен как один раз. Если это слишком сложно, матрица из 0s и 1s также даст мне некоторую информацию, хотя я бы предпочел сохранить как можно больше информации.

Есть ли у кого-нибудь идеи, как это сделать быстро? Существует 20 возможных кодов.

ответ

5

Пример:

my20chars = c(LETTERS[1:10], 0:9) 

set.seed(1) 
x = replicate(1e4, paste0(sample(c(my20chars,"-"),10, replace=TRUE), collapse="")) 

Один из подходов:

library(data.table) 

d = setDT(stack(strsplit(setNames(x,x),""))) 
dcast(d[ values %in% my20chars ], ind ~ values, fun = length) 

Результат:

   ind 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J 
    1: ---8EEAD8I 0 0 0 0 0 0 0 0 2 0 1 0 0 1 2 0 0 0 1 0 
    2: --33B6E-32 0 0 1 3 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 
    3: --3IFBG8GI 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 2 0 2 0 
    4: --4210I8H5 1 1 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0 
    5: --5H4DE9F- 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 1 0 1 0 0 
    ---             
9996: JJFJBJ24AJ 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 5 
9997: JJI-J-0FGB 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 3 
9998: JJJ1B54H63 0 1 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 1 0 3 
9999: JJJED7A3FI 0 0 0 1 0 0 0 1 0 0 1 0 0 1 1 1 0 0 1 3 
10000: JJJIF6GI13 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0 2 3 

контрольный показатель:

library(microbenchmark) 

nstrs = 1e5 
nchars = 10 
x = replicate(nstrs, paste0(sample(c(my20chars,"-"), nchars, replace=TRUE), collapse="")) 

microbenchmark(
dcast = { 
    d = setDT(stack(strsplit(setNames(x,x),""))) 
    dcast(d[ values %in% my20chars ], ind ~ values, fun = length, value.var="ind") 
}, 
times = 10) 

# Unit: seconds 
# expr  min  lq  mean median  uq  max neval 
# dcast 3.112633 3.423935 3.480692 3.494176 3.573967 3.741931 10 

Итак, это не так быстро, чтобы обрабатывать 75 миллионов строк OP, но может быть хорошим местом для начала.

+1

Просто заметил, что если строки появляются несколько раз, они получают объединены в результате. Например, если вы отбросите 'nchars' до типа' 3', вы увидите это. Не уверен, что это необходимо. – Frank

3

мне очень нравится @ решение Фрэнка, но вот другой способ, который имеет два преимущества:

  • Он использует редкий формат матрицы, так что вы, скорее всего, чтобы соответствовать все в памяти; и

  • Это (даже) проще.

Он использует наш quanteda пакет, где вы tokenise символов в каждой строке и образуют матрицу документа функции из них в одной команде:

my20chars = c(LETTERS[1:10], 0:9) 
set.seed(1) 
x = replicate(1e4, paste0(sample(c(my20chars,"-"),10, replace=TRUE), collapse="")) 

require(quanteda) 
myDfm <- dfm(x, what = "character", toLower = FALSE, verbose = FALSE) 
# for equivalent printing, does not change content: 
myDfm <- myDfm[, order(features(myDfm))] 
rownames(myDfm) <- x 
head(myDfm) 
# Document-feature matrix of: 6 documents, 20 features. 
# 6 x 20 sparse Matrix of class "dfmSparse" 
#    features 
# docs   0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J 
# FH29E8933B 0 0 1 2 0 0 0 0 1 2 0 1 0 0 1 1 0 1 0 0 
# ED4I605-H6 1 0 0 0 1 1 2 0 0 0 0 0 0 1 1 0 0 1 1 0 
# 9E3CFIAI8H 0 0 0 1 0 0 0 0 1 1 1 0 1 0 1 1 0 1 2 0 
# 020D746C5I 2 0 1 0 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 
# 736116A054 1 2 0 1 1 1 2 1 0 0 1 0 0 0 0 0 0 0 0 0 
# 08JFBCG03I 2 0 0 1 0 0 0 0 1 0 0 1 1 0 0 1 1 0 1 1 

Неудобство:

  • Это (много) медленнее.

Benchmark:

microbenchmark(
    dcast = { 
     d = setDT(stack(strsplit(setNames(x,x),""))) 
     dcast(d[ values %in% my20chars ], ind ~ values, fun = length, value.var="ind") 
    }, 
    quanteda = dfm(x, what = "character", toLower = FALSE, removePunct = FALSE, verbose = FALSE), 
    times = 10) 
# Unit: seconds 
#  expr  min  lq  mean median  uq  max naval 
#  dcast 2.380971 2.423677 2.465338 2.429331 2.521256 2.636102 10 
# quanteda 21.106883 21.168145 21.369443 21.345173 21.519018 21.883966 10 
Смежные вопросы