Pull to refresh

Comments 9

Спасибо за статью! Бывает непросто перестать мыслить циклами :)
Было бы интересно увидеть список задач, где без циклов не обойтись. Например, у меня такой кейс: есть вектор с названиями файлов формата json, нужно последовательно их считывать, далее в каждом файле считывать несколько подсписков (для каждого файла кол-во подсписков разное). Сейчас это реализовано двумя циклами for: внешний для считывания файлов и внутренний для прохода по всем подспискам. Можно ли это реализовать более эффективно без циклов?
На моем ноутбуке расчеты занимают 39 секунд, хотя того же результата можно достичь за 0,009 секунды
С точки зрения человека, далекого от R, это очень странная ситуация. Обработка массива данных всегда где-то под капотом сводится к циклу. Получается, что стандартная реализация цикла средствами языка несет столько накладных расходов, что выполняется в 4 тысячи раз медленнее «железного» цикла?

По-моему, эта проблема должна решаться оптимизациями на стороне компилятора — разворачивание циклов, SIMD и другие хитрости, как это делает, например, компилятор C. А добавлением целого семейства специализированных функций выглядит, как костыль.
Больше похоже на ленивое выполнение, когда в таблицу внесли запись вида «отдавать дополнительную колонку, в которой находится результат операции». А так как после этого данные никто и не читает, то реальной работы и не происходит.
Тогда получается, что сравнение вообще некорректно?
R интерпретируемый язык, поэтому циклы и неоптимизированы, а групповые операции как раз всю оптимизацию внутри циклов и имеют. Поэтому в R важно понимать что делаешь.
Думается, последнее полезно при работе не только в R.
Нет, просто во втором случае все работает параллельно. И R сам по себе на эту параллельность заточен. Вполне возможно что обычный цикл даже толком не оптимизирован — он не используется для больших данных. Но последнее — это уже домыслы.
for(row in 1:nrow(testDF))
testDF[row, 3] < — testDF[row, 1] + testDF[row, 2] # Ужас!

Согласен. «Ужас!». Но ведь — не «Ужас-ужас!»

Попробуйте «штатное» (т.е. без всяких библиотек) для R:

system.time(testDF$c<-testDF$a+testDF$b)


Будете приятно удивлены.

А про самый современный подход ничего не сказано. Функциональный подход на базе purrr. Интересующимся можно взглянуть для затравки на доклад с rstudio::conf 2017, почитать книгу R4DS, раздел "Итераторы". А еще есть более хитрые циклы, когда надо, например, применять функции с условием для определенных строк выбранных столбцов дата фрейма… А еще неплохо бы знать структуры данных и специфику используемых пакетов. Например, как быстро провести обработку data.frame с POSIXct с разными time-zone? Любой цикл "в лоб" даст безумное по исполнению время.

Sign up to leave a comment.