2014-03-25 4 views
1

Я задал подобный вопрос месяц назад. Обратитесь к Count the occurrences of unequal numbers from a data frameКак настроить внешние и векторизовать функции?

Я решил эту проблему с помощью outer и Vectorize функций. Мое решение таково:

dist_mat<- outer(1:nrow(df),1:nrow(df), 
       FUN = Vectorize(function(i,j) sum(df[i,]!=df[j,]))) 

Это работает отлично, но теперь у меня есть огромная матрица, которая превышает мой размер памяти.

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

Спасибо заранее!

+0

Ответы Роланда в другом вопросе также имеют проблемы с памятью? [Редактировать мой комментарий к дальнейшим соображениям: возможно, это происходит, так как это уменьшает количество операций чуть меньше половины, но добавляет еще два столбца.] Это было бы одним из способов исправить проблемы с памятью; если да, то векторизованные операции могли бы как-то использовать желаемые значения. – Aaron

ответ

1

Хотя это не строго ответить на ваш вопрос, вы, вероятно, следует избегать outer и использовать что-то вроде:

tot.rows <- nrow(df) 
res <- numeric(tot.rows) 
for(i in 1:tot.rows) 
    for(j in 1:tot.rows) 
    res[[i]] <- res[[i]] + (sum(df[i,] != df[j,]) <= 2) 

outer будет предварительно выделить i * j матрицу с самого начала идти, так что вы собираетесь с трудом справляются с проблемой при использовании внешнего. Если ваш результат на самом деле является вектором такой же длины, как и фрейм данных, то вам не нужно outer, который производит матрицу размеров nrow(df) * nrow(df) в вашем приложении.

Вышеупомянутый алгоритм будет работать с таким же количеством вычислений, как outer, но повторно использует то же пространство памяти для каждой строки, поскольку все, о чем вы заботитесь, - это окончательные подсчеты, поэтому он должен вписываться в память. Он также должен быть сопоставимой скорости, такой как внешний (для примера с игрушкой я тестировал его). Векторизованные операции велики, пока вам действительно нужно вычислять на каждое значение и иметь память для работы с полными расширениями, например outer, но они не обязательно являются ответом на все.

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

+0

Я пробовал это, прежде чем я пошел для векторизации.У меня нет проблемы с памятью, но она работает несколько часов. Вероятно, в течение нескольких дней (я остановил его через 6 часов или около того). – Chris

+0

@ Крис, версия 'outer' должна работать так же медленно. Вы сравнили производительность двух подходов на подмножестве ваших данных, достаточно малых, чтобы вписаться в память? Кроме того, кажется, вы действительно хотите ограничить вычисления теми, которые необходимы в этом случае. У вас есть дубликаты в ваших данных? Каковы ваши данные (числовые, факторные, характерные)? – BrodieG

+0

Вы правы, внешний тоже медленный. У меня есть тип данных факторов. Теперь я пытаюсь найти способ уменьшить свои данные. – Chris

1

Если у вас есть матрица DF затем

apply(DF, 2, function(y) sum(colSums(DF==y) < 2)) 

может работать? DF==y сравнивает каждый столбец с целевым столбцом от apply, colSums, затем выясняет, сколько строк в этой паре столбцов равно, и мы сравниваем это с 2 (целевой столбец всегда сравнивается с собой как часть DF = = y, поэтому я учитывал это, возможно, вам придется поиграть с этим, в зависимости от того, включал ли ваш порог «2» самоанализ). И тогда окончательный sum подсчитывает количество столбцов, удовлетворяющих порогу < 2.

Это полностью переупорядоченный код, исходя из предположения, что вам не нужна промежуточная матрица расстояния.

+0

Могут быть особенности ваших данных, которые могли бы сделать вещи более эффективными. например Вы можете удалить строки, которые не имеют дублирующих значений, используя 'apply (DF, 1, anyDuplicated) == 0' - каковы размеры df - есть ли множество комбинаций столбцов или длина столбцов? –

+0

Гэвин, я думаю, что OP пытается сравнивать строки, а не столбцы, и кажется, что вы делаете здесь противоположное (я думаю?)? – BrodieG

+0

A'DF <- t (DF) 'должен сортировать, если только я не интерпретировал его как столбцы на одном шаге и не строчил на другом, что вполне возможно! И, вероятно, стоит сравнить бенчмаркинг, который лучше всего работает с данными OPs, поскольку мы не знаем, длинный и тонкий, или короткий и широкий, и распространенность дубликатов и т. Д. –

Смежные вопросы