R: передача кадра данных по ссылке

R имеет семантику передачи по значению, которая сводит к минимуму случайные побочные эффекты (хорошо). Однако, когда код организован во множество функций / методов для повторного использования / читабельности / ремонтопригодности и когда этому коду необходимо управлять большими структурами данных через, например, большие фреймы данных, посредством серии преобразований / операций, семантика передачи по значению приводит к к большому количеству копирования данных и большому разбору кучи (плохая вещь). Например, кадр данных, занимающий 50 МБ в куче, который передается в качестве параметра функции, будет скопирован как минимум столько же раз, сколько и глубина вызова функции, а размер кучи внизу стека вызовов будет равен N * 50Мб. Если функции возвращают преобразованный / измененный фрейм данных из глубины цепочки вызовов, то копирование увеличивается на другой N.

Вопрос SO ​​Каков наилучший способ чтобы избежать передачи кадра данных? затрагивает эту тему, но формулируется таким образом, чтобы не задавать напрямую вопрос о передаче по ссылке, а в выигрышном ответе в основном говорится: «Да, передача по значению - это то, как R работает". На самом деле это не на 100% точно. Среды R поддерживают семантику передачи по ссылке, а структуры OO, такие как proto, используют эту возможность широко. Например, когда прото-объект передается как аргумент функции, а его «волшебная оболочка» передается по значению, разработчику R семантика передается по ссылке.

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

Если ничего не доступно, мой подход заключался бы в создании прото-объекта, который обертывает фрейм данных. Я был бы признателен за указатели на синтаксический сахар, который следует добавить к этому объекту, чтобы сделать его полезным, например, перегрузка операторов $ и [[, а также любые ошибки, на которые я должен обратить внимание. Я не эксперт по R.

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


person Sim    schedule 26.06.2012    source источник
comment
Я не думаю, что посылка в вашем вопросе верна. R копирует только при изменении, поэтому вы можете спокойно передавать аргументы вниз по стеку вызовов без создания новых копий, пока вы не изменяете объект. Я постараюсь найти вам несколько ссылок по этому поводу через минуту.   -  person Andrie    schedule 26.06.2012
comment
См., Например, этот вопрос и ответ на него @matthewdowle: stackoverflow.com/q/10225098/602276   -  person Andrie    schedule 26.06.2012
comment
Андри прав. Удивлен, что вы не нашли data.table при поиске большого data.frame. Что искали?   -  person Matt Dowle    schedule 26.06.2012
comment
@Andrie, спасибо, что указали на это. Я удивлен, что об этом не упоминалось в таких книгах, как Искусство программирования на R. Кажется, это фундаментальная особенность языка. Какое самое лучшее чтение о внутренностях R вы бы порекомендовали?   -  person Sim    schedule 26.06.2012


Ответы (1)


Предпосылка вопроса (частично) неверна. R работает как промежуточное обещание, и повторное копирование происходит так, как вы описываете, только тогда, когда выполняются дальнейшие назначения и изменения фреймворка данных по мере передачи обещания. Таким образом, количество копий будет не N * size, где N - глубина стека, а где N - количество уровней, на которых выполняются назначения. Вы правы, однако, окружающая среда может быть полезной. По ссылке я вижу, что вы уже нашли пакет «proto». Существует также относительно недавнее введение «эталонного класса», иногда называемого «R5», где R / S3 была исходной системой классов S3, которая копируется в R, а R4 будет более новой системой классов, которая, кажется, в основном поддерживает разработка пакета BioConductor.

Вот ссылка на пример Стива Лианоглу (в потоке, обсуждающем достоинства ссылочных классов) встраивания среды в объект S4, чтобы избежать затрат на копирование:

https://stat.ethz.ch/pipermail/r-help/2011-September/289987.html

Пакет «data.table» Мэтью Доула создает новый класс объекта данных, семантика доступа которого с использованием символа «[» отличается от семантики обычного R data.frames, и который действительно работает как передача по ссылке. Он имеет превосходную скорость доступа и обработки. Он также может использовать семантику фрейма данных, поскольку в более поздние годы такие объекты теперь наследуют класс data.frame.

Вы также можете изучить пакет фреймов данных Хестерберга.

person IRTFM    schedule 26.06.2012
comment
И +1 для ссылки на пакет dataframe, который теперь включен (или, по крайней мере, в философию) в R 2.15-1. - person Andrie; 26.06.2012
comment
@DWin, спасибо за информацию. Промежуточное обещание имеет смысл в качестве оптимизации, хотя в моем случае, когда несколько шагов работают с одним и тем же фреймом данных, превращая его из необработанного в обрабатываемый, это не помогает. Обычно модификации выполняются на отдельных этапах конвейера обработки, но в некоторых случаях они выполняются в той же цепочке вызовов, когда пересекаются границы абстракции с разными инвариантами. Я изучу рекомендуемые вами пакеты. - person Sim; 26.06.2012