我有一个目标管道,应该填充并使用 DBI 数据库(在本例中为 duckdb。出于性能原因选择 SQL 和 duckdb)。
如何有效地将
{targets}
与 SQL 表结合使用。
一个可重现的最小示例看起来像这样,它读取两个数据集,组合它们,创建一个模型和一个图。
# in _targets.R
library(targets)
# preparation once:
# d <- ggplot2::mpg |> dplyr::mutate(id = 1:dplyr::n())
# write_csv(d |> dplyr::select(id, cty), "data1.csv")
# write_csv(d |> dplyr::select(id, displ, cyl), "data2.csv")
get_data <- function(file) {
read_csv(file, col_types = cols()) %>%
as_tibble()
}
combine_data <- function(d1, d2) {
left_join(d1, d2, by = "id")
}
fit_model <- function(data) {
lm(cty ~ displ + cyl, data) |>
coefficients()
}
plot_model <- function(model, data) {
ggplot(data) +
geom_point(aes(x = displ, y = cty, color = cyl)) +
geom_abline(intercept = model[1], slope = model[2]) +
theme_gray(24)
}
tar_option_set(packages = c("tibble", "readr", "dplyr", "ggplot2"))
list(
tar_target(file1, "data1.csv", format = "file"),
tar_target(file2, "data2.csv", format = "file"),
tar_target(data1, get_data(file1)),
tar_target(data2, get_data(file2)),
tar_target(data, combine_data(data1, data2)),
tar_target(model, fit_model(data)),
tar_target(plot, plot_model(model, data))
)
# run: tar_make() -> runs all targets
# change a value in data2.csv -> tar_make() -> rebuilds only dependencies
这应该与数据库连接一起使用
# write to Database
con <- DBI::dbConnect(duckdb::duckdb(), "data.db")
on.exit(DBI::dbDisconnect(con, shutdown = TRUE), add = TRUE)
DBI::dbWriteTable(con, "data1", d |> dplyr::select(id, cty))
DBI::dbWriteTable(con, "data2", d |> dplyr::select(id, displ, cyl))
# in _targets.R... unclear at best...
list(
tar_target(data1, ???), # if I use DBI::dbReadTable(con, "data1") it duplicates the data and returns it to R
)
问题是,如果我将表的值返回给 R,这可能会花费太长时间。是否有针对目标的数据库感知适配器,这对于目标是否可能/有意?
我也经历过同样的尴尬,并因此创建了sqltargets。我现在使用的模式是:
load_tables_to_db <- function(...) {
tables <- lst(...)
path_to_db <- fs::path(Sys.getenv("S_DR_DP"), glue::glue("Databases/WFC_DB.duckdb"))
con <- DBI::dbConnect(
duckdb::duckdb(),
dbdir = path_to_db,
read_only = FALSE
)
on.exit(DBI::dbDisconnect(con, shutdown = TRUE))
walk2(tables, names(tables), \(df, nm) DBI::dbWriteTable(conn = con, name = nm, value = df, overwrite = TRUE))
}
在
_targets.R
:
tar_target(
tables_loaded_to_db,
load_tables_to_db(
table1,
table2,
...
)
),
tar_sql(report1, "query1.sql"),
tar_sql(report2, "query2.sql")
tar_sql
将创建文件的上游目标(例如“report1_query_file”),而“report1”包含查询结果。 SQL 文件的标头中必须包含连接字符串。可以在注释中指定依赖关系(例如“--tar_load(table1)”)
该软件包是全新的,仍然是 WIP,但可能有助于简化您的工作流程。