4

该表reg_data是 PostgreSQL 表。事实证明,在 PostgreSQL 中运行回归更快。但是,当我为 100,000 个数据集运行它时,我想逐个数据集地执行它,并将每个数据集的结果附加到一个表中。

有没有办法使用原生dplyr动词将 PostgreSQL 数据附加到 PostgreSQL 表中?我不确定将数据带到 R 然后将它们发送回 PostgreSQL 的成本很高(它只有 6 个数字和几个标识字段),但它看起来确实不优雅。

library(dplyr)

pg <- src_postgres()

reg_data <- tbl(pg, "reg_data")

reg_results <-
    reg_data %>%
    summarize(r_squared=regr_r2(y, x),
              num_obs=regr_count(y, x),
              constant=regr_intercept(y, x),
              slope=regr_slope(y, x),
              mean_analyst_fog=regr_avgx(y, x),
              mean_manager_fog=regr_avgy(y, x)) %>%
    collect() %>%
    as.data.frame()

# Push to database.
dbWriteTable(pg$con, c("bgt", "within_call_data"), reg_results,
             append=TRUE, row.names=FALSE)
4

2 回答 2

4

dplyr不包括在数据库中插入或更新记录的命令,因此没有完整的本地dplyr解决方案。但是您可以将 dplyr 与常规 SQL 语句结合起来,以避免将数据带到 R 中。

collect()让我们从在声明之前重现您的步骤开始

library(dplyr)

pg <- src_postgres()

reg_data <- tbl(pg, "reg_data")

reg_results <-
    reg_data %>%
    summarize(r_squared=regr_r2(y, x),
              num_obs=regr_count(y, x),
              constant=regr_intercept(y, x),
              slope=regr_slope(y, x),
              mean_analyst_fog=regr_avgx(y, x),
              mean_manager_fog=regr_avgy(y, x))

现在,您可以使用compute()而不是collect()在数据库中创建一个临时表。

temp.table.name <- paste0(sample(letters, 10, replace = TRUE), collapse = "")

reg_results <- reg_results %>% compute(name=temp.table.name)

temp.table.name随机表名在哪里。使用计算中的选项name = temp.table.name,我们将此随机名称分配给创建的临时表。

现在,我们将使用该库RPostgreSQL创建一个插入查询,该查询使用存储在临时表中的结果。由于临时表只存在于我们创建的连接中,src_postgresql()我们需要重用它。

library(RPostgreSQL)
copyconn <- pg$con
class(copyconn) <- "PostgreSQLConnection" # I get an error if I don't fix the class

最后插入查询

sql <- paste0("INSERT INTO destination_table SELECT * FROM ", temp.tbl.name,";")

dbSendQuery(copyconn, sql)

所以,一切都在数据库中发生,数据并没有被带入 R。

编辑

当我们temp.tbl.namereg_results. 使用计算中的选项可以避免这种情况name=

于 2016-08-30T08:04:16.230 回答
3

另一种选择是使用调用命令sql_render()创建每个 SQL 语句,然后调用另一个命令db_save_query()使用 SQL 语句创建表,然后使用手动语句附加到表。要遍历每个查询,请使用purrr命令:mapwalk。最好,类似command 的compute()命令应该这样做,但取而代之的是,以下是一个完全可重现的示例:

library(dplyr)
library(dbplyr)
library(purrr)

# Setting up a SQLite db with 3 tables
con <- DBI::dbConnect(RSQLite::SQLite(), path = ":memory:")
copy_to(con, filter(mtcars, cyl == 4), "mtcars1")
copy_to(con, filter(mtcars, cyl == 6), "mtcars2")
copy_to(con, filter(mtcars, cyl == 8), "mtcars3")



# Pre-process the SQL statements
tables <- c("mtcars1","mtcars2","mtcars3")
all_results <- tables %>%
  map(~{
    tbl(con, .x) %>%
      summarise(avg_mpg = mean(mpg),
                records = n()) %>%
      sql_render() 
  })

# Execute the SQL statements, 1st one creates the table
# subsquent queries are insterted to the table
first_query <- TRUE
all_results %>%
  walk(~{
    if(first_query == TRUE){
      first_query <<- FALSE
      db_save_query(con, ., "results")
    } else {
      dbExecute(con, build_sql("INSERT INTO results ", .))
    }
  })


tbl(con, "results")

dbDisconnect(con)
于 2017-09-24T18:51:30.883 回答