在阅读之前我有必要进行申明,因为使用的是RMD文档,所以每次RENDER的时候都会读取数据库,所以结果显示不一样正常,有的也加了
overwrite和append选项。显示的结果不一定与实际读者操作的结果一致。
内容:
- 了解关系型数据库
- 使用SQL工具
使用数据库能够有效地应对超出计算机内存容量的数据存储问题,还可以根据用户提供的条件,对数据库中的数据进行查询,这也使在数据库中更新现有记录和插入新数据的操作变得简单。
操作关系型数据库
关系型数据库就是一个由表和表之间的关系组成的集合。数据库中的表和R中的数据框有相同地形式。表之间可以互相关联,让我们能够轻松合并多张表信息。
下面从最简单数据库开始,SQLite(http://sqlite.org/)是一个轻量级的数据库引擎。
在R中操作SQLite数据库需要用RSQLite扩展包。运行下面代码:
if(!require("RSQLite")) install.packages("RSQLite")
#> 载入需要的程辑包:RSQLite
创建SQLite数据库
现在在博客R目录下创建一个data目录,用来存储数据库:
if (!dir.exists("../../R/data")) dir.create("../../R/data")
接下来载入RSQLite包,提供数据库驱动SQLite()和数据库文件example.sqlite建立连接。如果目标文件不存在,数据库驱动会创建一个新的空文件,即空SQLite数据库:
library(RSQLite)
con = dbConnect(SQLite(), "../../R/data/example.sqlite")
数据库连接con是介于用户和系统中间的一层。我们可以创建一个连接,并且连接到关系型数据库,并通过这个连接实现查询、抽取以及更新数据。后续将一直使用这个连接,直到这个连接被关闭。
我们可以在关系数据库中创建新表,表看起来和R里的数据框是一样的。
下面创建一个数据框,并将它作为表插入数据库中。
example1 = data.frame(
id = 1:5,
type = c("A", "A", "B", "B", "C"),
score = c(8, 9, 8, 10, 9),
stringsAsFactors = FALSE
)
example1
#> id type score
#> 1 1 A 8
#> 2 2 A 9
#> 3 3 B 8
#> 4 4 B 10
#> 5 5 C 9
现在进行写入:
dbWriteTable(con, "example1", example1, overwrite = TRUE)
接下来使用dbDisconnect()断开数据库连接,这样con便不可用了。
dbDisconnect(con)
向一个数据库写入多张表格
现在我们将ggplot2的diamonds数据集和nycflights13中的flights数据集作为两张表格写入数据库中。
if(!require("ggplot2")) install.packages("ggplot2")
#> 载入需要的程辑包:ggplot2
if(!require("nycflights13")) install.packages("nycflights13")
#> 载入需要的程辑包:nycflights13
data("diamonds", package = "ggplot2")
data("flights", package = "nycflights13")
我们重复之前的操作流程:
con = dbConnect(SQLite(), "../../R/data/datasets.sqlite")
dbWriteTable(con, "diamonds", diamonds, row.names = FALSE, overwrite = TRUE)
dbWriteTable(con, "flights", flights, row.names = FALSE, overwrite = TRUE)
dbDisconnect(con)
这里使用overwrite=TRUE的目的是防止多次添加同一张表报错。
现在数据库中有两张表了。
向表中追加数据
下面先生成几个数据块,然后增加到数据库的表中:
con = dbConnect(SQLite(), "../../R/data/example2.sqlite")
# 先移除之前的表
dbRemoveTable(con, "products")
chunk_size = 10
id = 0
for (i in 1:6){
chunk = data.frame(id = ((i - 1L) * chunk_size):(i * chunk_size -1L),
type = LETTERS[[i]],
score = rbinom(chunk_size, 10, (10-i)/10),
stringsAsFactors = FALSE)
dbWriteTable(con, "products", chunk,
append = i > 1, row.names = FALSE)
}
dbDisconnect(con)
每次代码块都生成一个数据框,包含一些确定数据和随机数,我们将这些数据记录追加到一个名为products的表中。
访问表和表中字段
当有了数据库和数据,我们可以进行数据访问。比如所有表的名字或某个表的列。
con = dbConnect(SQLite(), "../../R/data/datasets.sqlite")
使用dbExistsTable()可以检查数据库是否存在某张表:
dbExistsTable(con, "diamonds")
#> [1] TRUE
dbExistsTable(con, "mtcars")
#> [1] FALSE
下面列出该数据库的所有表:
dbListTables(con)
#> [1] "diamond_selector" "diamonds" "flights"
对于某一张表,我们可以使用dbListFields()列出表的列名(或字段):
dbListFields(con, "diamonds")
#> [1] "carat" "cut" "color" "clarity" "depth" "table" "price"
#> [8] "x" "y" "z"
与dbWriteTable()相反,adReadTable()将表格读入为数据框:
db.diamonds = dbReadTable(con, "diamonds")
dbDisconnect(con)
head(db.diamonds)
#> carat cut color clarity depth table price x y z
#> 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43
#> 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31
#> 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
#> 4 0.29 Premium I VS2 62.4 58 334 4.20 4.23 2.63
#> 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
#> 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48
str(db.diamonds)
#> 'data.frame': 53940 obs. of 10 variables:
#> $ carat : num 0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
#> $ cut : chr "Ideal" "Premium" "Good" "Premium" ...
#> $ color : chr "E" "E" "E" "I" ...
#> $ clarity: chr "SI2" "SI1" "VS1" "VS2" ...
#> $ depth : num 61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
#> $ table : num 55 61 65 58 58 57 57 55 61 61 ...
#> $ price : int 326 326 327 334 335 336 336 337 337 338 ...
#> $ x : num 3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
#> $ y : num 3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
#> $ z : num 2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...







网友评论