Я не могу больше подчеркнуть разницу в эффективности между двумя! Хотя это правда, что DF более удобны в некоторых случаях анализа данных, они также допускают разнородные данные, и некоторые библиотеки принимают их только, но все это на самом деле вторично, если вы не пишете одноразовый код для конкретной задачи.
Позвольте привести пример. Была функция, которая вычисляла бы 2D путь метода MCMC. По сути, это означает, что мы берем начальную точку (x, y) и повторяем определенный алгоритм, чтобы найти новую точку (x, y) на каждом шаге, таким образом создавая весь путь. Алгоритм включает в себя вычисление довольно сложной функции и генерацию некоторой случайной величины на каждой итерации, поэтому, когда она запускалась в течение 12 секунд, я думала, что это нормально, учитывая, сколько вещей она делает на каждом шаге. При этом функция собрала все точки в построенном пути вместе со значением целевой функции в data-frame из трех столбцов. Таким образом, 3 столбца не так велики, и число шагов также было более чем разумным 10000 (в этом типе проблем типичны пути длиной 1 000 000, поэтому 10 000 - это ничто). Итак, я думал, что DF 10,000x3 определенно не проблема. Причина использования DF проста. После вызова функции был вызван ggplot (), чтобы нарисовать результирующий (x, y) -path. И ggplot () не принимает матрицу.
Затем в какой-то момент из любопытства я решил изменить функцию, чтобы собирать путь в матрице. Радостно, что синтаксис DF и матриц похож, все, что я сделал, это изменил строку, указав df как data.frame, на строку, инициализировав ее как матрицу. Здесь я также должен упомянуть, что в исходном коде DF был инициализирован, чтобы иметь окончательный размер, поэтому позже в коде функции только новые значения были записаны в уже выделенные пробелы, и не было никаких дополнительных затрат на добавление новых строк в DF. Это делает сравнение еще более справедливым, а также упрощает мою работу, поскольку мне не нужно было ничего переписывать в функции. Изменение только одной строки от первоначального размещения data.frame требуемого размера на матрицу того же размера. Чтобы адаптировать новую версию функции к ggplot (), я преобразовал теперь возвращенную матрицу в data.frame для использования в ggplot ().
После повторного запуска кода я не мог поверить в результат. Код запускается за доли секунды! Вместо примерно 12 секунд. И снова, функция в течение 10 000 итераций считывает и записывает значения только в уже выделенные пространства в DF (а теперь и в матрице). И эта разница также для разумного (или, скорее, небольшого) размера 10000x3.
Итак, если ваша единственная причина использовать DF - сделать его совместимым с библиотечной функцией, такой как ggplot (), вы всегда можете преобразовать его в DF в последний момент - работать с матрицами настолько, насколько вам кажется удобный. Если, с другой стороны, есть более существенная причина для использования DF, например, вы используете какой-то пакет анализа данных, который в противном случае потребовал бы постоянного преобразования из матриц в DF и обратно, или вы не выполняете интенсивные вычисления самостоятельно и используете только стандартные пакеты (многие из них на самом деле внутренне преобразуют DF в матрицу, выполняют свою работу, а затем преобразуют результат обратно - так, что они выполняют всю эффективную работу за вас), или выполняют разовую работу, чтобы вам было все равно удобнее с DF, тогда вам не стоит беспокоиться об эффективности.
Или другое, более практичное правило: если у вас есть вопрос, такой как в OP, используйте матрицы, чтобы вы использовали DF только тогда, когда у вас нет такого вопроса (поскольку вы уже знаете, что должны использовать DF, или потому что вам на самом деле все равно, так как код разовый и т. д.).
Но в целом всегда помните об этой точке эффективности как о приоритетной.