Каков наилучший способ избежать передачи фрейма данных?

У меня есть 12 data.frame для работы. Они похожи, и я должен сделать одну и ту же обработку для каждого, поэтому я написал функцию, которая принимает data.frame, обрабатывает ее, а затем возвращает data.frame. Это работает. Но я боюсь, что я прохожу мимо очень большой структуры. Я могу делать временные копии (я?) Это не может быть эффективным. Каков наилучший способ избежать передачи data.frame вокруг?

doSomething <- function(df) {
  // do something with the data frame, df
  return(df)
}

Ответ 1

Вы, действительно, передаете объект и используете некоторую память. Но я не думаю, что вы можете сделать операцию над объектом в R, не проходя вокруг объекта. Даже если вы не создали функцию и не выполняли свои операции вне функции, R будет вести себя в основном одинаково.

Лучший способ увидеть это - создать пример. Если вы находитесь в Windows, откройте диспетчер задач Windows. Если вы находитесь в Linux, откройте окно терминала и запустите верхнюю команду. В этом примере я предполагаю Windows. В R выполните следующие действия:

col1<-rnorm(1000000,0,1)
col2<-rnorm(1000000,1,2)
myframe<-data.frame(col1,col2)

rm(col1)
rm(col2)
gc()

это создает пару векторов, называемых col1 и col2, затем объединяет их в кадр данных, называемый myframe. Затем он отбрасывает векторы и заставляет мусорную корзину запускать. Посмотрите в своем диспетчере задач Windows при использовании mem для задачи Rgui.exe. Когда я запускаю R, он использует около 19 мегабайт памяти. После выполнения приведенных выше команд моя машина использует менее 35 мегабайт для R.

Теперь попробуйте следующее:

myframe<-myframe+1

ваше использование памяти для R должно перепрыгнуть более 144 мегабайт. Если вы выберете сборку мусора с помощью gc(), вы увидите, что она опустится примерно до 35 мегабайт. Чтобы попробовать это с помощью функции, вы можете сделать следующее:

doSomething <- function(df) {
    df<-df+1-1
return(df)
}
myframe<-doSomething(myframe)

когда вы запускаете код выше, использование памяти будет увеличиваться до 160 мегабайт или около того. Запуск gc() вернет его обратно до 35 мегабайт.

Так что же из всего этого сделать? Ну, делать операцию вне функции не намного эффективнее (с точки зрения памяти), чем выполнять ее в функции. Сбор мусора очищает вещи до хорошего. Должны ли вы принудительно запускать gc()? Вероятно, не так, как он будет запускаться автоматически по мере необходимости, я просто использовал его выше, чтобы показать, как он влияет на использование памяти.

Я надеюсь, что это поможет!

Ответ 2

Я не эксперт R, но большинство языков используют схему подсчета ссылок для больших объектов. Копия данных объекта не будет сделана до тех пор, пока вы не измените копию объекта. Если ваши функции только считывают данные (т.е. Для анализа), то копия не должна делаться.

Ответ 3

Я столкнулся с этим вопросом, ища что-то еще, и он старый - поэтому я просто дам короткий ответ на этот вопрос (оставьте комментарий, если вы хотите получить больше объяснений).

Вы можете передавать окружения в R, которые содержат от 1 до всех ваших переменных. Но, вероятно, вам не нужно беспокоиться об этом.

[Вы также можете сделать что-то подобное с классами. Я только сейчас понимаю, как использовать классы для полиморфных функций - и обратите внимание на то, что существует более чем одна классная система.]