Как читать огромный файл csv в R по условию строки?

У меня огромный файл csv около 15 миллионов строк с размером около 3G.

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

например. один из столбцов называется типом продукта, поэтому мне нужно только прочитать один тип продукта в R, а затем обработать его, а затем вывести результат, после чего я перейду к другому типу продукта...

До сих пор я читал о различных методах, таких как загрузка большого файла в базу данных или чтение столбца по столбцу с помощью colbycol или чтение фрагмента строк с помощью ff...

любое чистое решение R может решить мою проблему?

Ответ 1

Вы можете использовать пакет RSQLite:

library(RSQLite)
# Create/Connect to a database
con <- dbConnect("SQLite", dbname = "sample_db.sqlite")

# read csv file into sql database
# Warning: this is going to take some time and disk space, 
#   as your complete CSV file is transferred into an SQLite database.
dbWriteTable(con, name="sample_table", value="Your_Big_CSV_File.csv", 
    row.names=FALSE, header=TRUE, sep = ",")

# Query your data as you like
yourData <- dbGetQuery(con, "SELECT * FROM sample_table LIMIT 10")

dbDisconnect(con)

В следующий раз, когда вы захотите получить доступ к своим данным, вы можете оставить dbWriteTable, так как таблица SQLite хранится на диске.

Примечание: запись CSV-данных в файл SQLite сначала не загружает все данные в память. Таким образом, память, которую вы будете использовать в конце, будет ограничена количеством данных, возвращаемых вашим запросом.

Ответ 2

Это можно сделать только с помощью R:

  • открыть подключение к файлу
  • если есть заголовок, затем прочитайте в информации заголовка
  • прочитайте одну строку из файла, используя read.csv с указанием colClasses и nrows=1
  • проверьте эту строку, чтобы убедиться, что она соответствует вашим условиям, добавьте ее в растущий фрейм данных, если да
  • повторите шаг 4 для остальной части файла.
  • закрыть соединение

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

Ответ 3

Вы также можете использовать JDBC для этого. Позвольте создать образец csv файла.

write.table(x=mtcars, file="mtcars.csv", sep=",", row.names=F, col.names=T) # create example csv file

Загрузите и сохраните драйвер CSV JDBC по этой ссылке: http://sourceforge.net/projects/csvjdbc/files/latest/download, а затем настройте драйвер.

> library(RJDBC)

> path.to.jdbc.driver <- "jdbc//csvjdbc-1.0-18.jar"
> drv <- JDBC("org.relique.jdbc.csv.CsvDriver", path.to.jdbc.driver)
> conn <- dbConnect(drv, sprintf("jdbc:relique:csv:%s", getwd())) # replace getwd() with location of csv file

Посмотрите на верхние 3 строки в наборе данных mtcars:

> head(dbGetQuery(conn, "select * from mtcars"), 3)
   mpg cyl disp  hp drat    wt  qsec vs am gear carb
1   21   6  160 110  3.9  2.62 16.46  0  1    4    4
2   21   6  160 110  3.9 2.875 17.02  0  1    4    4
3 22.8   4  108  93 3.85  2.32 18.61  1  1    4    1

Далее, давайте посмотрим на отдельные шестерни столбцов значений и соответствующие подсчеты:

> dbGetQuery(conn, "select gear, count(*) from mtcars group by gear")
  GEAR COUNT(*)
1    4       12
2    3       15
3    5        5

Теперь вы можете составить запрос, используя предложение where, чтобы фильтровать данные, чтобы выбирать только строки, где шестерня принимает значение 5:

> dbGetQuery(conn, "select * from mtcars where gear = '5'")
   mpg cyl  disp  hp drat    wt qsec vs am gear carb
1   26   4 120.3  91 4.43  2.14 16.7  0  1    5    2
2 30.4   4  95.1 113 3.77 1.513 16.9  1  1    5    2
3 15.8   8   351 264 4.22  3.17 14.5  0  1    5    4
4 19.7   6   145 175 3.62  2.77 15.5  0  1    5    6
5   15   8   301 335 3.54  3.57 14.6  0  1    5    8