Ошибка: исчерпана память (достигнут предел?) из-за внешней функции

Я разработал скрипт, в котором обрабатывал два больших массива (оба по тысяче строк), «родительский» и «продуктовый».

Начальный набор данных выглядит примерно так:

parent<-sample(1:10000,3500)
product<-sample(1:7500,2500)
mztol<-0.0015
mzdiff<-sample(1:1000,31)
names(mzdiff)<-c("d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
             "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", 
             "d19", "d20", "d21", "d22", "d23", "d24", "d25", 
             "d26","d27,"d28", "d29", "d30",
             "d31")

Сначала я применил внешнюю функцию, чтобы получить матрицу различий между двумя массивами поэлементно.

tabdiff<-outer(product,parent,'-')

Затем я попытался поэлементно вычесть табдифф матрицы с вектором (mzdiff), чтобы оценить, есть ли элементы ‹= значение (mztol). Я сделал это с помощью внешней функции.

subfun<-function(x,y) abs(x-y)<=mztol
vsubfun<-Vectorize(subfun)
vlogres<-outer(tabdiff,mzdiff,vsubfun)

Здесь я получил вектор, каждый элемент которого является логической матрицей. Затем я преобразовал его в список:

listres<-alply(vlogres,3,.dims=T)

и поставил в доказательство только ИСТИННЫЕ элементы и подсчитал их:

result<-sapply(listres, function(x) table(x)["TRUE"])

Ну, дело в том, что скрипт работает нормально, если я разрабатываю только небольшие векторы родителей и продуктов, например:

parent<-sample(1:1000,150)
product<-sample(1:1500,500)

Если я рассматриваю большие, я получаю сообщение об ошибке «ошибка: исчерпана память (достигнут предел?)», когда он обрабатывает vlogres. Предположим, у меня есть рабочая станция с 16 ГБ оперативной памяти. Но все равно терпит неудачу.

Итак, как я могу оптимизировать этот сценарий, чтобы избежать сообщения об ошибке? Любой намек?


person AeonRed    schedule 06.12.2017    source источник
comment
Вероятно, помогло бы, если бы вы предоставили небольшой воспроизводимый пример того, что вы пытаетесь сделать (не воспроизводить ошибку).   -  person CPak    schedule 06.12.2017
comment
Ты прав. Только что отредактировал ;)   -  person AeonRed    schedule 06.12.2017
comment
Привет. Ваш ввод - это всего два массива. Что они представляют? Как они стеснены? Какое отношение к этому имеют имена? Когда результат, учитывая, что вводится? Вы, кажется, выражаете решение с точки зрения огромных промежуточных отношений, которые вам не нужны. PS Re теги не имеют в виду внешний продукт, а не внешнее соединение.   -  person philipxy    schedule 16.12.2017
comment
Привет Филипп. Я имею дело с химическими данными (функции ЖХ-МС/МС). Родитель - это вектор, относящийся к исходным соединениям, молекулам, которые могут подвергаться фрагментации, которая может давать один или несколько продуктов. У каждой родительской молекулы и молекулы-продукта есть характеристика, известная как m/z (значения, которые вы можете найти в векторах-родителях и продуктах). Итак, я хотел бы выяснить, какой вид фрагментации имеет место, и, следовательно, понять, есть ли связь между родителем и составным продуктом.   -  person AeonRed    schedule 26.12.2017
comment
По разнице этих двух векторов (элемент за элементом) у меня есть матрица значений (tabdiff), которая показывает мне некоторую информацию о процессах фрагментации (фрагментация подразумевает потерю m/z, если родитель развивается в продукте). Следовательно, каждый элемент этой матрицы необходимо сравнивать с заданными значениями (mzdiff). Если один из них соответствует значению mzdiff, у меня фактическая фрагментация. Итак, я хотел бы упростить и ускорить сравнение tabdiff с mzdiff. Кстати, я хотел бы иметь вывод, в котором мои результаты сообщаются по каждому значению mzdiff.   -  person AeonRed    schedule 26.12.2017


Ответы (1)


Самое простое решение, которое я могу придумать, - это перебрать tabdiff как одномерный вектор.

tabdiff<-c(outer(product, parent, '-'))
result <- sapply(tabdiff, function(i) sum(abs(i-mzdiff) <= mztol))

Оператор sapply должен выполнять то, что вы хотите, но вы должны дважды проверить его. Это устраняет задачу сохранения данных размером m * n * p.


Другая идея состоит в том, чтобы подумать о своей проблеме задом наперед. Вам нужны значения product - parent, которые находятся в пределах допустимого порога (mztol) каждого mzdiff. Это означает, что вам нужны значения product - parent в диапазоне mzdiff +/- mztol. Вы можете создать векторы значений верхней и нижней границы для каждого mzdiff и использовать dplyr::between или более быстрый data.table::inrange, чтобы найти, какие значения находятся в диапазоне.

person CPak    schedule 06.12.2017
comment
Ну, если честно, мне нужно что-то большее. Да, 1d вектор все упрощает, но в то же время я потеряю всю информацию о том, кто есть кто. Я имею в виду, что мне нужно легко отслеживать каждый элемент, чтобы понять, какой родитель и продукт дают совпадение. Так что n-мерный формат полезен для меня, потому что это аккуратный и чистый способ сохранить мои данные (для каждого mzdiff у меня есть логическая матрица родителя и продукта). Кстати, я протестирую другой подход, который вы мне предложили. Спасибо. - person AeonRed; 07.12.2017