Попытка избавиться от этой ошибки: невозможно выделить вектор размером 500 мб - PullRequest
1 голос
/ 26 марта 2020

Пробовал gc(), увеличение memory.limit(), похоже, ничего не работает. Использование 64 бита R. Data.frame df имеет 32 миллиона строк и имеет размер приблизительно 4 ГБ; df2 относительно маленький. Я удалил все переменные из глобальной среды, кроме df и df2. Ошибка появляется после строки sqldf кода ниже.

Может кто-нибудь помочь мне с эквивалентом этого кода в пакете data.table, чтобы увидеть, если использование, которое разрешает переполнение стека:

df <- sqldf(
  'select A.*, 
  case when A.cost is null then B.meancost else A.cost end imputedcost 
  from df A 
  left join df2 B on A.ID = B.ID'
)

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Я предполагаю, что вы пытаетесь использовать sqldf для манипуляции здесь, потому что df и df2 довольно велики, так как 500 МБ не должно быть достаточно, чтобы вызвать переполнение стека самостоятельно. Выпускаются две возможности:

  • В данный момент в вашей памяти много других данных (df и df2 могут быть очень большими)
  • Сжатие левого соединения df и df2 сжимается больше памяти, чем указывает ошибка

Возможные решения:

  • Замените левое соединение чем-то более дружественным по памяти. Является ли средняя стоимость переменной в таблице B или stati c? т.е. это может быть просто число?
  • Попробуйте выполнить это преобразование, используя data.table вместо sqldf. sqldf не очень быстр в вычислительном отношении при такой работе, что предполагает, что он может быть менее эффективным с точки зрения памяти.
  • Разбейте наборы данных на более мелкие части, чтобы R мог уместить все это в памяти
  • Выполните эти преобразования в реальной среде SQL, предназначенной для обработки больших преобразований данных, а не в R, где все хранится в памяти. Вы можете использовать PostgreSQL для взаимодействия со средой SQL через R.
0 голосов
/ 27 марта 2020

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

Ничего не нужно настраивать. Это делает все это. Просто добавьте dbname = tempfile() к вашему выражению sqldf.

sqldf(...whatever..., dbname = tempfile())

Следующее не будет иметь никакого значения для использования памяти, но в качестве примечания, что вы можете написать этот запрос как:

sqldf('select A.*, coalesce(A.cost, B.meancost) as newcost
  from df A
  left join df2 B using(ID)`)
...