R (64-бит на Windows): как обойти ошибку «невозможно выделить вектор размером 557,6 Мб» в коде - PullRequest
0 голосов
/ 03 февраля 2020

Это продолжение моего более раннего вопроса о том, как найти сравнение определенного атрибута между двумя текстовыми файлами.

Благодаря принятому ответу я собрал код ниже, который работает (в моей системе) на меньших наборах данных:

library(tidyverse, data.table)

con1  <- file("file1.csv", open = "r")
con2  <- file("file2.csv", open = "r")

file1 <- select(read.csv(con1, sep = "|", fill = F, colClasses = "character"),
                PROFILE.ID, USERID)

setDT(file1)

file2 <- select(read.csv(con2, sep = "|", fill = F, colClasses = "character"),
                PROFILE.ID, USERID)

setDT(file2)

full_join(file1, file2, by = "USERID") %>%
  filter(is.na(PROFILE.ID.x) | is.na(PROFILE.ID.y) |
                PROFILE.ID.x != PROFILE.ID.y)

close(con1)
close(con2)

Проблема: Когда R начинает обработку функции full_join, он в конечном итоге останавливается с ошибкой cannot allocate vector of size 557.6 Mb.

Среда: Это 64-битная версия R v.3.6.2 на Windows 10 ОС, а memory.limit () возвращает 16222. У меня нет других загруженных объектов в R за исключением того, что загружено вышеуказанным кодом.

Возможная причина: Проблема, вероятно, связана с тем, что два CSV-файла имеют около 120K строк и 83 столбца в каждом.

То, что я пробовал до сих пор, но без решения проблемы:

  • Включено использование функции select () для удаления ненужных столбцов.
  • Включено использование data.table и setDT () для преобразования кадров данных в таблицу данных es.
  • Закрыты все приложения с видимым пользовательским интерфейсом (Outlook, Google Chrome, Excel и т. д. c).

Независимо от того, что я пытался всегда, ошибка относится к "557,6 Мб". Я не могу добавить больше оперативной памяти к этой машине в данный момент, так как это ноутбук компании.

Вопрос: Есть ли способ загрузить файлы порциями или каким-либо другим способом (в писать код) чтобы обойти ошибку?

1 Ответ

0 голосов
/ 06 февраля 2020

Мое первое решение здесь состояло в том, чтобы удалить те строки из файла file1 и file2, где USERID пуст.

Это не идеальное решение (учитывая, что merge, вероятно, более дружественно к DT, чем соединение функционирует в dplyr) в соответствии с комментарием, сделанным @ r2evans.

Так что более эффективным решением, вероятно, была бы замена full_join слиянием, например,

merge (file1, file2, by = "USERID", все = TRUE) [is.na (PROFILE.ID.x) | is.na (PROFILE.ID.y) | PROFILE.ID.x! = PROFILE.ID.y,]

Но первое решение, которое я попытался исправить проблему, заключалось в добавлении строк file1 <- filter(file1, USERID != "") и file2 <- filter(file2, USERID != "") в код.

В итоге код выглядел так:

library(tidyverse, data.table)

con1  <- file("file1.csv", open = "r")
con2  <- file("file2.csv", open = "r")

file1 <- select(read.csv(con1, sep = "|", fill = F, colClasses = "character"),
                PROFILE.ID, USERID)

file1 <- filter(file1, USERID != "")
setDT(file1)

file2 <- select(read.csv(con2, sep = "|", fill = F, colClasses = "character"),
                PROFILE.ID, USERID)

file2 <- filter(file2, USERID != "")
setDT(file2)

full_join(file1, file2, by = "USERID") %>%
  filter(is.na(PROFILE.ID.x) | is.na(PROFILE.ID.y) |
                PROFILE.ID.x != PROFILE.ID.y)

close(con1)
close(con2)
...