For-loop vs foreach vs apply и самые быстрые объекты для обработки данных?

Я надеюсь, что кто-то более осведомленный, чем я, поможет оптимизировать этот код. Я пробовал несколько методов, в том числе foreach с doparallel (и snow) и компилятором, но я думаю, что могут быть более простые способы улучшить код, например, изменить фреймы данных на таблицы данных / матрицы и, возможно, вместо этого предварительно загрузить пустые объекты. конкатенации векторов в цикле.

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

s.ids = коэффициент длиной 66510. Не заметил разницы в скорости при изменении на вектор символов.

g.list = символьный вектор длиной 978.

l_signatures = матрица 978x66511.

d_g_up и d_g_down = небольшие фреймы данных (nx10, n в диапазоне от 5 до 200) с метаданными, относящимися к g.list

c_score_new() вычисляет счет. Это достаточно сложно, чтобы изменить его в этом сценарии. Ожидается, что e_signature будет иметь 2 столбца, один из которых состоит из g.list («идентификаторы»), а другой - как соответствующие «ранги», созданные с помощью: rank(-1 * l_signatures[,as.character(id)], ties.method = "random")

for (id in s.ids) {
    e_signature <- data.frame(g.list,
                              rank(-1 * l_signatures[, as.character(id)],
                                   ties.method = "random"))    
    colnames(e_signature) <- c("ids","rank")
    d_scores <- c(d_scores, c_score_new(d_g_up$Symbol, d_g_down$Symbol, e_signature))
}

Итого, это занимает 5-10 минут для вычисления, из которых 3-5 минут связаны с генерацией e_signature, что не является сложным в вычислительном отношении. Вот где я подозреваю, что оптимизация может принести наибольшую пользу.

Если бы мы сделали цикл для генерации e_signature более эффективным способом и объединили результаты в 1 объект (978x66510) перед выполнением c_score_new(), это могло бы быть быстрее?

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
427
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Наибольшее количество времени занимает rank. Можно сократить время вычислений более чем на 50%, т.е. заменить base::rank с циклом for на Rfast::colRanks, см. Ниже:

library(microbenchmark)
library(Rfast)

n <- 978
m <- 40000 #66510

x <- matrix(rnorm(n * m), ncol = m)

microbenchmark(
  Initial = {
    for (i in 1:ncol(x)) { 
      base::rank(x[, i], ties.method = "random")
    }
  },
  Optimized = {

    colRanks(x, method = "min")
  },
  times = 1
)

Выход:

Unit: seconds
      expr      min       lq     mean   median       uq      max neval
   Initial 8.092186 8.092186 8.092186 8.092186 8.092186 8.092186     1
 Optimized 3.397526 3.397526 3.397526 3.397526 3.397526 3.397526     1

Я очень ценю ваш комментарий! Вчера я пробовал это пару раз, но не увидел улучшений. Я попробовал еще раз сегодня после перехода в RMD, чтобы, надеюсь, исключить некоторые ошибки, но получил то же самое - без улучшений. Старое время: 7,4 - 7,9 минут, новое время: 7,8-7,9 минут. Я думаю, что дисперсия случайна. Я думаю, ты что-то понял. Мне нужно выяснить, чем мои объекты отличаются от ваших.

pnoob 24.08.2018 16:27

Я заметил огромный прирост производительности с точки зрения генерации df, как показано выше. Он генерируется практически мгновенно. К сожалению, когда я запускаю анализ (c_score_new ()), мне приходится брать столбцы из этого df в цикле, и я теряю 100% этого времени (все еще в сумме ~ 7,5 минут). Хотел бы я дать вам больше, чем положительный голос; Я очень ценю, что вы смотрите на это для меня!

pnoob 30.08.2018 17:31

К сожалению, без дальнейших подробностей о функции c_score_new его довольно сложно оптимизировать. Например. пожалуйста, проверьте также причину, по которой вы отправляете в цикле d_g_up$Symbol, d_g_down$Symbol - но они неизменяемы в цикле for.

Artem 30.08.2018 18:25

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

Artem 30.08.2018 18:52

Другие вопросы по теме