Ускорение вложенной петли;Это может быть векторизация? - PullRequest
3 голосов
/ 03 октября 2011

Я пытаюсь сопоставить некоторые данные относительно того, что может быть довольно большим набором данных, и даже для набора данных среднего размера это занимает слишком много времени.

Задача, которую я выполняю, - решить механическую проблему, затем вернуться на 6 месяцев назад и искать процедурные проблемы (сбои со стороны отдельных сотрудников). Сначала я сопоставляю по машине и местоположению, поэтому хочу сопоставить одно и то же место с той же машиной. Тогда я требую, чтобы процедурная ошибка предшествовала механической, поскольку в будущем. Наконец, я ограничиваюсь 180 днями, чтобы все было сопоставимо.

На этапе построения данных я ограничиваю механические проблемы, чтобы исключить первые 6 месяцев, поэтому у меня есть один и тот же 180-дневный блок для каждого.

Я немного прочитал об оптимизирующих циклах. Я знаю, что вы хотите создать переменную хранения вне цикла, а затем просто добавить к ней, но на самом деле я понятия не имею, сколько совпадений она вернет, поэтому изначально я использовал rbind внутри цикла. Я знаю, что верхняя граница для переменных хранения - это количество механических проблем * количество процедурных проблем, но это гигантское значение, и я не могу выделить такой большой вектор. В коде, который я здесь размещаю, используется мой макс. Размер переменной хранения, но я думаю, что мне придется вернуться к чему-то вроде этого:

if (counter == 1) {
    pro = procedural[i, ]
    other = mechanical[j, ]
}
if (counter != 1) {
    pro = rbind(pro, procedural[i, ])
    other = rbind(other, mechanical[j, ])
}

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

Я также попытался удалить второй цикл и просто использовать команду which, но, похоже, это не работает с полным столбцом данных (из процедурных данных), сравниваемым с одним значением (из механических данных).

Вот код, который у меня есть в настоящее время. Хорошо работает для небольших наборов данных, но для всего, что удаленно велико, это занимает вечность.

maxval = mechrow * prorow
pro = matrix(nrow = maxval, ncol = ncol(procedural))
other = matrix(nrow = maxval, ncol = ncol(procedural))
numprocissues = matrix(nrow = mechrow, ncol = 1)
counter = 1
for (j in 1:mechrow) {
    for (i in 1:prorow) {
        if (procedural[i, 16] == mechanical[j, 16] &
            procedural[i, 17] < mechanical[j, 17] &
            procedural[i, 2] == mechanical[j, 2] &
            abs(procedural[i, 17] - mechanical[j, 17]) < 180) {

            pro[counter, ] = procedural[i, ]
            other[counter, ] = mechanical[j, ]
            counter = counter + 1
        }
    }
    numprocissues[j, 1] = counter
}

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

Любой совет будет принята с благодарностью!

Спасибо.

1 Ответ

6 голосов
/ 03 октября 2011

Непроверено ...

xy <- expand.grid(mech=1:mechrow, pro=1:prorow)
ok <- (procedural[xy$pro, 16] == mechanical[xy$mech, 16] &
       procedural[xy$pro, 17] <  mechanical[xy$mech, 17] &
       procedural[xy$pro,  2] == mechanical[xy$mech,  2] &
       abs(procedural[xy$pro, 17] -  mechanical[xy$mech, 17]) < 180)
pro   <- procedural[xy$pro[ok],]
other <- mechanical[xy$mech[ok],]
numprocissues <- tapply(ok, xy$mech, sum)
...