Импортируйте несколько файлов CSV в базу данных postgresql, используя r (ошибка памяти) - PullRequest
2 голосов
/ 19 апреля 2020

Я пытаюсь импортировать набор данных (со многими CSV-файлами) в r и затем записать данные в таблицу в базе данных postgresql.

Я успешно подключился к базе данных, создал al oop импортировать CSV-файлы и попытался импортировать. Затем R возвращает ошибку, потому что моему p c не хватает памяти.

Мой вопрос: есть ли способ создать al oop, который импортирует файлы один за другим, записывает их в postgresql таблица и впоследствии удаляет их? Таким образом, я не исчерпал бы память.

Код, который возвращает ошибку памяти:

`#connect to PostgreSQL database
db_tankdata <- 'tankdaten'  
host_db <- 'localhost'
db_port <- '5432'
db_user <- 'postgres'  
db_password <- 'xxx'
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, dbname = db_tankdata, host=host_db, 
                 port=db_port, user=db_user, password=db_password)

#check if connection was succesfull
dbExistsTable(con, "prices")

#create function to load multiple csv files
import_csvfiles <- function(path){
  files <- list.files(path, pattern = "*.csv",recursive = TRUE, full.names = TRUE)
  lapply(files,read_csv) %>% bind_rows() %>% as.data.frame()
    }


#import files
prices <- import_csvfiles("path...")
dbWriteTable(con, "prices", prices , append = TRUE, row.names = FALSE)`

Заранее спасибо за отзыв!

Ответы [ 2 ]

2 голосов
/ 19 апреля 2020

Если вы измените lapply() на включение анонимной функции, вы можете прочитать каждый файл и записать его в базу данных, уменьшив объем необходимой памяти. Поскольку lapply() действует как подразумеваемое for() l oop, вам не нужен дополнительный механизм зацикливания.

import_csvfiles <- function(path){
     files <- list.files(path, pattern = "*.csv",recursive = TRUE, full.names = TRUE)
     lapply(files,function(x){ 
          prices <- read.csv(x) 
          dbWriteTable(con, "prices", prices , append = TRUE, row.names = FALSE)
          })
}
0 голосов
/ 19 апреля 2020

Я предполагаю, что ваши CSV-файлы очень большие, которые вы импортируете в базу данных? Насколько мне известно, R сначала хочет сохранить данные в кадре данных с кодом, который вы написали, сохраняя данные в памяти. Альтернативой будет чтение CSV-файла в блоках, как вы это делаете с Python Pandas.

При вызове ?read.csv я увидел следующий вывод:

nrows: максимальное количество строк для чтения. Отрицательные и другие недопустимые значения игнорируются.

skip: количество строк файла данных, которые нужно пропустить перед началом чтения данных.

Почему бы вам не попытаться прочитать 5000 строк за раз в блок данных, записать в базу данных PostgreSQL и затем сделать это для каждого файла.

Для Например, для каждого файла сделайте следующее:

number_of_lines = 5000                 # Number of lines to read at a time
row_skip = 0                           # number of lines to skip initially
keep_reading = TRUE                    # We will change this value to stop the while

while (keep_reading) {
    my_data <- read.csv(x, nrow = number_of_lines , skip = row_skip)
    dbWriteTable(con, "prices", my_data , append = TRUE, row.names = FALSE) # Write to the DB

    row_skip = 1 + row_skip + number_of_lines   # The "1 +" is there due to inclusivity avoiding duplicates

# Exit Statement: if the number of rows read is no more the size of the total lines to read per read.csv(...)
if(nrow(my_data) < number_of_lines){
   keep_reading = FALSE
    } # end-if    
} # end-while

Делая это, вы разбиваете CSV на более мелкие части. Вы можете поиграть с переменной number_of_lines, чтобы уменьшить количество циклов. Это может показаться немного хакерским с вовлечением всех oop, но я уверен, что это будет работать

...