将多个文件的数据存入一个数据库

在处理大数据文件时,常常在读写数据方面遇到许多问题。实际可能出现两种极端情
况。一种是文本格式的数据源非常大,几乎不能载入内存。另一种是:数据分散在许多文
件中,需要费些力气将它们整合到一个数据框中。
对于第 1 种情况,我们可以逐块地读取数据,并将每块数据分别追加到数据库的

某张表中。以下函数便是为此设计的,给定输入文件、输出数据库、表名和数据块的
容量,该函数向数据库的表中追加记录。考虑到输入数据可能过大,以至于无法载入
内存,所以这个函数每次只会读取一块数据,并将其写入数据库,因此,只需要很小
的工作内存:
chunk_rw <- function(input, output, table, chunk_size = 10000) {
first_row <- read.csv(input, nrows = 1, header = TRUE)
header <- colnames(first_row)
n <- 0
con <- dbConnect(SQLite(), output)
on.exit(dbDisconnect(con))
while (TRUE) {
df <- read.csv(input,
skip = 1 + n * chunk_size,nrows = chunk_size,
header = FALSE, col.names = header,
stringsAsFactors = FALSE)
if (nrow(df) == 0) break
dbWriteTable(con, table, df, row.names = FALSE, append = n > 0)
n <- n + 1
cat(sprintf("%d records written\n", nrow(df)))
}
}
因为是逐块进行操作,所以技巧性在于正确地计算输入文件中每个数据块的偏移量。
为了测试这个函数,我们先将 diamonds 写入一个 csv 文件,再用 chunk_rw( ) 逐
块地将 csv 文件写入 SQLite 数据库。用这种办法,写入过程只需要非常小的工作内存,远
远小于将整个数据载入所需的内存。
write.csv(diamonds, "data/diamonds.csv", quote = FALSE, row.names = FALSE)
chunk_ _rw("data/diamonds.csv", "data/diamonds.sqlite", "diamonds")
## 10000 records written
## 10000 records written
## 10000 records written
## 10000 records written
## 10000 records written
## 3940 records written
另一种极端的情况是,我们需要从很多个小文件中读取数据。在这种情况下,我们可
以把分布在这些文件中的所有数据写入到一个数据库,以便轻松地实现查询。下面这个函
数将一个文件夹中的所有 csv 文件的数据导入一个数据库中:
batch_rw <- function(dir, output, table, overwrite = TRUE) {
files <- list.files(dir, "\\.csv$", full.names = TRUE)
con <- dbConnect(SQLite(), output)
on.exit(dbDisconnect(con))
exist <- dbExistsTable(con, table)
if (exist) {
if (overwrite) dbRemoveTable(con, table)
else stop(sprintf("Table '%s' already exists", table))
}
exist <- FALSE
for (file in files) {
cat(file, "... ")
df <- read.csv(file, header = TRUE,
stringsAsFactors = FALSE)
dbWriteTable(con, table, df, row.names = FALSE,
append = exist)
exist <- TRUE
cat("done\n")
}
}
为了演示,我们在 data/groups 中放入多个小的 csv 格式文件,调用 batch_
rw( ) 将所有数据导入数据库。
batch_ _rw("data/groups", "data/groups.sqlite", "groups")
## data/groups/group1.csv ... done
## data/groups/group2.csv ... done
## data/groups/group3.csv ... done
现在,所有文件中的数据都被放进数据库了。我们读取整个表来看看最终效果:
con <- dbConnect(SQLite(), "data/groups.sqlite")
dbReadTable(con, "groups")
## group id grade
## 1 1 I-1 A
## 2 1 I-2 B
## 3 1 I-3 A
## 4 2 II-1 C
## 5 2 II-2 C
## 6 3 III-1 B
## 7 3 III-2 B
## 8 3 III-3 A
## 9 3 III-4 C
dbDisconnect(con)
## [1] TRUE
本节介绍了 SQLite 数据库的基本知识和用法。实际上,许多流行的关系型数据库的功
能特征和查询语句基本类似。掌握这些通用知识,就可以使用各种工具操作不同的关系型
数据库,例如,通过 RMySQL 操作 MySQL,通过 RPostges 操作 PostreSQL,通
过 RSQLServer 操 作 Microsoft SQL , 或 者 通 过 RODBC 操 作 ODBC 兼 容 数 据 库
(Microsoft Access 和 Excel)。它们的操作方法相同,因此,熟悉了其中一种,操作其他几
种应该也不成问题。

posted @ 2019-02-11 11:23  NAVYSUMMER  阅读(382)  评论(0编辑  收藏  举报
交流群 编程书籍