Вопрос

У меня есть два рамы данных df1 а также df2 Каждый из них имеет около 10 миллионов рядов и 4 столбца. Я читаю их в r, используя Rodbc/sqlquery без проблем, но когда я пытаюсь rbind их, я получаю это самое страшное из сообщений об ошибках R: cannot allocate memory. Анкет Должны быть более эффективные способы сделать rbind Более эффективно - у кого -нибудь есть свои любимые уловки в этом, которым они хотят поделиться? Например, я нашел этот пример в DOC для sqldf:

# rbind
a7r <- rbind(a5r, a6r)
a7s <- sqldf("select * from a5s union all select * from a6s")

Это лучший/рекомендуемый способ сделать это?

ОБНОВИТЬЯ получил его работать, используя решающий dbname = tempfile() аргумент в sqldf звоните выше, как предлагает JD Long в своем ответе этот вопрос

Это было полезно?

Решение

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

# create two sample files
DF1 <- data.frame(A = 1:2, B = 2:3)
write.table(DF1, "data1.dat", sep = ",", quote = FALSE)
rm(DF1)

DF2 <- data.frame(A = 10:11, B = 12:13)
write.table(DF2, "data2.dat", sep = ",", quote = FALSE)
rm(DF2)

# now we do the real work
library(sqldf)

data1 <- file("data1.dat")
data2 <- file("data2.dat")

sqldf(c("select * from data1", 
 "insert into data1 select * from data2", 
 "select * from data1"), 
 dbname = tempfile())

Это дает:

>  sqldf(c("select * from data1", "insert into data1 select * from data2", "select * from data1"), dbname = tempfile())
   A  B
1  1  2
2  2  3
3 10 12
4 11 13

Эта более короткая версия также работает, если заказ строки не имеет значения:

sqldf("select * from data1 union select * from data2", dbname = tempfile())

Смотрите домашнюю страницу SQLDF http://sqldf.googlecode.com а также ?sqldf для получения дополнительной информации. Обратите особое внимание на аргументы формата файла, так как они близки, но не идентичны read.table. Анкет Здесь мы использовали значения по умолчанию, так что это было меньше.

Другие советы

Обратите внимание на data.table R пакет для эффективных операций на объектах с более чем несколькими миллионами записей.

Версия 1.8.2 этого пакета предлагает rbindlist функция, через которую вы можете достичь того, что вы хотите очень эффективно. Таким образом, вместо rbind(a5r, a6r) Вы можете:

library(data.table)
rbindlist(list(a5r, a6r))

Попробуйте создать data.frame желаемого размера, следовательно, импортируйте ваши данные, используя подписки.

dtf <- as.data.frame(matrix(NA, 10, 10))
dtf1 <- as.data.frame(matrix(1:50, 5, 10, byrow=TRUE))
dtf2 <- as.data.frame(matrix(51:100, 5, 10, byrow=TRUE))
dtf[1:5, ] <- dtf1
dtf[6:10, ] <- dtf2

я думаю что rbind Расбор объекта без предварительного выделения его размеров ... Я не уверен, что это всего лишь предположение. Сегодня вечером я расчесываю "r adferno" или "манипулирование данными с R". Может быть merge сделает свое дело ...

РЕДАКТИРОВАТЬ

И вы должны иметь в виду, что (возможно) ваша система и/или R не могут справиться с чем -то таким большим. Попробуйте Revolution, может быть, вам удастся сэкономить время/ресурсы.

Для полноты в этой теме по теме Union: ING большие файлы, попробуйте использовать команды Shell в файлах для их объединения. В Windows есть команда «Копировать» с флагом/B ». Пример:

system(command =
         paste0(
           c("cmd.exe /c COPY /Y"
             , '"file_1.csv" /B'
             , '+ "file_2.csv" /B'
             , '"resulting_file.csv" /B'
           ), collapse = " "
         )
)#system

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top