⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
R API

Installation

duckdb: R API

可以使用以下命令安装DuckDB R API:

install.packages("duckdb")

详情请参阅安装页面

duckplyr: dplyr API

DuckDB 提供了一个与 dplyr 兼容的 API,通过 duckplyr 包实现。可以使用 install.packages("duckplyr") 进行安装。详情请参阅 duckplyr 文档

参考手册

DuckDB R API 的参考手册可在 R.duckdb.org 获取。

Basic API Usage

标准的DuckDB R API实现了R的DBI接口。如果您还不熟悉DBI,请参阅使用DBI页面以获取介绍。

启动与关闭

要使用DuckDB,您首先需要创建一个表示数据库的连接对象。连接对象将数据库文件作为参数进行读写。如果数据库文件不存在,它将被创建(文件扩展名可以是.db.duckdb或其他任何内容)。特殊值:memory:(默认值)可用于创建内存数据库。请注意,对于内存数据库,没有数据会持久化到磁盘(即,当您退出R进程时,所有数据都会丢失)。如果您想以只读模式连接到现有数据库,请将read_only标志设置为TRUE。如果多个R进程希望同时访问同一个数据库文件,则需要只读模式。

library("duckdb")
# to start an in-memory database
con <- dbConnect(duckdb())
# or
con <- dbConnect(duckdb(), dbdir = ":memory:")
# to use a database file (not shared between processes)
con <- dbConnect(duckdb(), dbdir = "my-db.duckdb", read_only = FALSE)
# to use a database file (shared between processes)
con <- dbConnect(duckdb(), dbdir = "my-db.duckdb", read_only = TRUE)

当连接超出范围或使用dbDisconnect()显式关闭时,连接会隐式关闭。要关闭与连接关联的数据库实例,请使用dbDisconnect(con, shutdown = TRUE)

Querying

DuckDB 支持标准的 DBI 方法来发送查询并检索结果集。dbExecute() 用于不期望返回结果的查询,如 CREATE TABLEUPDATE 等,而 dbGetQuery() 用于产生结果的查询(例如,SELECT)。下面是一个示例。

# create a table
dbExecute(con, "CREATE TABLE items (item VARCHAR, value DECIMAL(10, 2), count INTEGER)")
# insert two items into the table
dbExecute(con, "INSERT INTO items VALUES ('jeans', 20.0, 1), ('hammer', 42.2, 2)")

# retrieve the items again
res <- dbGetQuery(con, "SELECT * FROM items")
print(res)
#     item value count
# 1  jeans  20.0     1
# 2 hammer  42.2     2

DuckDB 还支持在 R API 中使用 dbExecutedbGetQuery 方法的预处理语句。以下是一个示例:

# prepared statement parameters are given as a list
dbExecute(con, "INSERT INTO items VALUES (?, ?, ?)", list('laptop', 2000, 1))

# if you want to reuse a prepared statement multiple times, use dbSendStatement() and dbBind()
stmt <- dbSendStatement(con, "INSERT INTO items VALUES (?, ?, ?)")
dbBind(stmt, list('iphone', 300, 2))
dbBind(stmt, list('android', 3.5, 1))
dbClearResult(stmt)

# query the database using a prepared statement
res <- dbGetQuery(con, "SELECT item FROM items WHERE value > ?", list(400))
print(res)
#       item
# 1 laptop

警告 请不要使用预处理语句将大量数据插入DuckDB。请参阅以下更好的选项。

高效传输

要将R数据框写入DuckDB,请使用标准的DBI函数dbWriteTable()。这将在DuckDB中创建一个表,并用数据框的内容填充它。例如:

dbWriteTable(con, "iris_table", iris)
res <- dbGetQuery(con, "SELECT * FROM iris_table LIMIT 1")
print(res)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa

也可以“注册”一个R数据框作为虚拟表,类似于SQL中的VIEW。这实际上还没有将数据传输到DuckDB中。以下是一个示例:

duckdb_register(con, "iris_view", iris)
res <- dbGetQuery(con, "SELECT * FROM iris_view LIMIT 1")
print(res)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa

DuckDB在注册后保留对R数据框的引用。这可以防止数据框被垃圾回收。当连接关闭时,引用会被清除,但也可以使用duckdb_unregister()方法手动清除。

另请参阅数据导入文档以获取更多高效导入数据的选项。

dbplyr

DuckDB 也能很好地与 dbplyr / dplyr 包配合使用,用于从 R 进行程序化查询构建。以下是一个示例:

library("duckdb")
library("dplyr")
con <- dbConnect(duckdb())
duckdb_register(con, "flights", nycflights13::flights)

tbl(con, "flights") |>
  group_by(dest) |>
  summarise(delay = mean(dep_time, na.rm = TRUE)) |>
  collect()

使用dbplyr时,可以使用dplyr::tbl函数读取CSV和Parquet文件。

# Establish a CSV for the sake of this example
write.csv(mtcars, "mtcars.csv")

# Summarize the dataset in DuckDB to avoid reading the entire CSV into R's memory
tbl(con, "mtcars.csv") |>
  group_by(cyl) |>
  summarise(across(disp:wt, .fns = mean)) |>
  collect()
# Establish a set of Parquet files
dbExecute(con, "COPY flights TO 'dataset' (FORMAT PARQUET, PARTITION_BY (year, month))")

# Summarize the dataset in DuckDB to avoid reading 12 Parquet files into R's memory
tbl(con, "read_parquet('dataset/**/*.parquet', hive_partitioning = true)") |>
  filter(month == "3") |>
  summarise(delay = mean(dep_time, na.rm = TRUE)) |>
  collect()

Memory Limit

你可以使用memory_limit配置选项来限制DuckDB的内存使用,例如:

SET memory_limit = '2GB';

请注意,此限制仅适用于DuckDB使用的内存,不会影响其他R库的内存使用。 因此,R进程使用的总内存可能高于配置的memory_limit

Troubleshooting

在macOS上安装时的警告

在macOS上,安装DuckDB可能会导致警告unable to load shared object '.../R_X11.so'

Warning message:
In doTryCatch(return(expr), name, parentenv, handler) :
  unable to load shared object '/Library/Frameworks/R.framework/Resources/modules//R_X11.so':
  dlopen(/Library/Frameworks/R.framework/Resources/modules//R_X11.so, 0x0006): Library not loaded: /opt/X11/lib/libSM.6.dylib
  Referenced from: <31EADEB5-0A17-3546-9944-9B3747071FE8> /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/modules/R_X11.so
  Reason: tried: '/opt/X11/lib/libSM.6.dylib' (no such file) ...
> ')

请注意,这只是一个警告,所以最简单的解决方案是忽略它。或者,您可以从R-universe安装DuckDB:

install.packages("duckdb", repos = c("https://duckdb.r-universe.dev", "https://cloud.r-project.org"))

你也可以通过Homebrew安装可选的xquartz依赖项