#performance #r #loops #for-loop #runtime
#Производительность #r #циклы #для цикла #время выполнения
Вопрос:
Я пытаюсь сопоставить некоторые данные с тем, что может быть довольно большим набором данных, и даже для набора данных среднего размера это занимает слишком много времени.
Задача, которую я выполняю, состоит в том, чтобы решить механическую проблему, затем вернуться на 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] amp;
procedural[i, 17] < mechanical[j, 17] amp;
procedural[i, 2] == mechanical[j, 2] amp;
abs(procedural[i, 17] - mechanical[j, 17]) < 180) {
pro[counter, ] = procedural[i, ]
other[counter, ] = mechanical[j, ]
counter = counter 1
}
}
numprocissues[j, 1] = counter
}
Места, которые, по моему мнению, можно улучшить, находятся в моей переменной хранилища, потенциальной векторизации, изменении условий в операторе if или, может быть, в инструкции fancy which для удаления цикла.
Любые советы будут с благодарностью!
Спасибо.
Комментарии:
1. Не могли бы вы опубликовать небольшой образец набора данных, чтобы сделать ваш код воспроизводимым?
2. Вы читали R inferno Патрика Бернса? Он рассказывает о создании вашего объекта, используемого для выполнения цикла, а затем время от времени разворачивает его. Превосходит rbind в любой день. burns-stat.com/pages/Tutor/R_inferno.pdf
3. Привет, Энди! Мне показалось, что ваша картинка выглядит знакомой…
4. Привет, Аарон! Это действительно я. Stackedoverflow великолепен.
5. Кто-нибудь знает, как получить таблицу или что-нибудь здесь? Я чувствую, что должен быть в состоянии, но это не выскакивает у меня.
Ответ №1:
Непроверено…
xy <- expand.grid(mech=1:mechrow, pro=1:prorow)
ok <- (procedural[xy$pro, 16] == mechanical[xy$mech, 16] amp;
procedural[xy$pro, 17] < mechanical[xy$mech, 17] amp;
procedural[xy$pro, 2] == mechanical[xy$mech, 2] amp;
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)
Комментарии:
1. Черт возьми, это действительно умно. Я провел выборочную проверку, и ok выдает правильное количество совпадений, а numprocissues также является правильным. Единственное, с чем я сталкиваюсь, это то, что pro и other имеют правильное количество строк и столбцов, и первые 3 строки pro заполняются вместе с первой строкой other, но тогда остальное — это просто NAs. Я собираюсь поиграть с этим и посмотреть, смогу ли я пройти мимо этого. Еще раз спасибо, это действительно отличная идея.
2. Вот чего не хватало: pro = процедурный [xy [ok,2],] другое = механический [xy [ok, 1],] Еще раз спасибо! Отсутствие необходимости выполнять циклы — лучшее чувство в мире.