如何使用 dplyr 将本地数据放入只读数据库?
How do I get local data into a read-only database using dplyr?
WRDS 是为学术界和商业及相关领域的其他研究人员提供研究数据的领先供应商。
WRDS提供了一个PostgreSQL数据库,但是这个是只读数据库。
对于某些任务,无法将数据写入数据库是非常受限的。例如,如果我想 运行 使用每日股票 returns 的事件研究,我需要将我的(相对较小的)本地数据集 events
与 crsp.dsf
合并,这大约是18GB的数据。
一个选择是使用 crsp.dsf
的副本维护我自己的数据库,并将 events
写入该数据库并合并到那里。但我正在寻找一个允许我为此目的使用 WRDS 数据库的选项。不幸的是,无法使用 copy_to
或 dbWriteTable
,因为 WRDS 数据库是只读的。
一个选项是使用类似于以下函数的东西,它使用 SQL 将本地数据帧转换为远程数据帧,即使在使用只读连接时也是如此.
df_to_pg <- function(df, conn) {
collapse <- function(x) paste0("(", paste(x, collapse = ", "), ")")
names <- paste(DBI::dbQuoteIdentifier(conn, names(df)), collapse = ", ")
values <-
df %>%
lapply(DBI::dbQuoteLiteral, conn = conn) %>%
purrr::transpose() %>%
lapply(collapse) %>%
paste(collapse = ",\n")
the_sql <- paste("SELECT * FROM (VALUES", values, ") AS t (", names, ")")
temp_df_sql <- dplyr::tbl(conn, dplyr::sql(the_sql))
return(temp_df_sql)
}
这是正在使用的函数的说明。功能已经在 PostgreSQL 和 SQL 服务器上测试过,但不能在 SQLite 上运行(由于缺少以这种方式工作的 VALUES
关键字)。
我相信它应该适用于 MySQL 或 Oracle,因为它们具有 VALUES
关键字。
library(dplyr, warn.conflicts = FALSE)
library(DBI)
pg <- dbConnect(RPostgres::Postgres())
events <- tibble(firm_ids = 10000:10024L,
date = seq(from = as.Date("2020-03-14"),
length = length(firm_ids),
by = 1))
events
#> # A tibble: 25 x 2
#> firm_ids date
#> <int> <date>
#> 1 10000 2020-03-14
#> 2 10001 2020-03-15
#> 3 10002 2020-03-16
#> 4 10003 2020-03-17
#> 5 10004 2020-03-18
#> 6 10005 2020-03-19
#> 7 10006 2020-03-20
#> 8 10007 2020-03-21
#> 9 10008 2020-03-22
#> 10 10009 2020-03-23
#> # … with 15 more rows
events_pg <- df_to_pg(events, pg)
events_pg
#> # Source: SQL [?? x 2]
#> # Database: postgres [iangow@/tmp:5432/crsp]
#> firm_ids date
#> <int> <date>
#> 1 10000 2020-03-14
#> 2 10001 2020-03-15
#> 3 10002 2020-03-16
#> 4 10003 2020-03-17
#> 5 10004 2020-03-18
#> 6 10005 2020-03-19
#> 7 10006 2020-03-20
#> 8 10007 2020-03-21
#> 9 10008 2020-03-22
#> 10 10009 2020-03-23
#> # … with more rows
由 reprex package (v1.0.0)
创建于 2021-04-01
WRDS 是为学术界和商业及相关领域的其他研究人员提供研究数据的领先供应商。 WRDS提供了一个PostgreSQL数据库,但是这个是只读数据库。
对于某些任务,无法将数据写入数据库是非常受限的。例如,如果我想 运行 使用每日股票 returns 的事件研究,我需要将我的(相对较小的)本地数据集 events
与 crsp.dsf
合并,这大约是18GB的数据。
一个选择是使用 crsp.dsf
的副本维护我自己的数据库,并将 events
写入该数据库并合并到那里。但我正在寻找一个允许我为此目的使用 WRDS 数据库的选项。不幸的是,无法使用 copy_to
或 dbWriteTable
,因为 WRDS 数据库是只读的。
一个选项是使用类似于以下函数的东西,它使用 SQL 将本地数据帧转换为远程数据帧,即使在使用只读连接时也是如此.
df_to_pg <- function(df, conn) {
collapse <- function(x) paste0("(", paste(x, collapse = ", "), ")")
names <- paste(DBI::dbQuoteIdentifier(conn, names(df)), collapse = ", ")
values <-
df %>%
lapply(DBI::dbQuoteLiteral, conn = conn) %>%
purrr::transpose() %>%
lapply(collapse) %>%
paste(collapse = ",\n")
the_sql <- paste("SELECT * FROM (VALUES", values, ") AS t (", names, ")")
temp_df_sql <- dplyr::tbl(conn, dplyr::sql(the_sql))
return(temp_df_sql)
}
这是正在使用的函数的说明。功能已经在 PostgreSQL 和 SQL 服务器上测试过,但不能在 SQLite 上运行(由于缺少以这种方式工作的 VALUES
关键字)。
我相信它应该适用于 MySQL 或 Oracle,因为它们具有 VALUES
关键字。
library(dplyr, warn.conflicts = FALSE)
library(DBI)
pg <- dbConnect(RPostgres::Postgres())
events <- tibble(firm_ids = 10000:10024L,
date = seq(from = as.Date("2020-03-14"),
length = length(firm_ids),
by = 1))
events
#> # A tibble: 25 x 2
#> firm_ids date
#> <int> <date>
#> 1 10000 2020-03-14
#> 2 10001 2020-03-15
#> 3 10002 2020-03-16
#> 4 10003 2020-03-17
#> 5 10004 2020-03-18
#> 6 10005 2020-03-19
#> 7 10006 2020-03-20
#> 8 10007 2020-03-21
#> 9 10008 2020-03-22
#> 10 10009 2020-03-23
#> # … with 15 more rows
events_pg <- df_to_pg(events, pg)
events_pg
#> # Source: SQL [?? x 2]
#> # Database: postgres [iangow@/tmp:5432/crsp]
#> firm_ids date
#> <int> <date>
#> 1 10000 2020-03-14
#> 2 10001 2020-03-15
#> 3 10002 2020-03-16
#> 4 10003 2020-03-17
#> 5 10004 2020-03-18
#> 6 10005 2020-03-19
#> 7 10006 2020-03-20
#> 8 10007 2020-03-21
#> 9 10008 2020-03-22
#> 10 10009 2020-03-23
#> # … with more rows
由 reprex package (v1.0.0)
创建于 2021-04-01