使用ggplot2中的geom_函数调用postgreSQL plr中编写的函数

使用ggplot2中的geom_函数调用postgreSQL plr中编写的函数,r,postgresql,ggplot2,plr,R,Postgresql,Ggplot2,Plr,我很难从R脚本调用postgreSQL中的plr函数,并在ggplot2-geom_函数中使用它。下面的例子非常简单,但希望能说明这个问题 假设我有以下plr功能: CREATE OR REPLACE FUNCTION public.mypgfunc( x numeric, a numeric) RETURNS numeric LANGUAGE 'plr' COST 100 VOLATILE PARALLEL UNSAFE AS $BODY$

我很难从R脚本调用postgreSQL中的plr函数,并在ggplot2-geom_函数中使用它。下面的例子非常简单,但希望能说明这个问题

假设我有以下plr功能:

CREATE OR REPLACE FUNCTION public.mypgfunc(
    x numeric,
    a numeric)
    RETURNS numeric
    LANGUAGE 'plr'
    COST 100
    VOLATILE PARALLEL UNSAFE
AS $BODY$
    return (x*a)
$BODY$;
要从ggplot-geom_函数调用这个函数,我可以编写以下简单的包装函数来执行查询(我使用rpostgres包):

如果我将plr函数写在R中,并从geom_函数调用它,那么一切都正常。 如果我直接调用myWrapper(在ggplot之外),分别使用x和a的一个值,那么一切都可以正常工作


那么,我必须改变什么呢?

我现在不太了解如何在R中使用SQL数据库。但我想我知道您错误的原因

如果您查看
stat_function
(这是
geom_function
在引擎盖下使用的功能)的帮助页面,您将看到,默认情况下,它在任意范围内创建101个x值(我认为是[0,1])

这就是错误消息提到“查询需要2个参数;提供102”的原因。调用
dbBind(q,c(x,a))
时,将
x
(长度为101的向量)与
a
(长度为1)连接在一起

x
的大小由参数
n
定义。因此,如果你跑步:

ggplot() + geom_function(fun = myWrapper , args = list(a = 5), n=1)
您正在将单个值
x
传递给
myWrapper
(我认为
x=0
),您应该会得到与上一句中描述的情况相同的结果(我收到一条警告消息,因为ggplot无法用一个点画一条线)

因此,基本上,您需要对向量
x
的每个值进行单独的查询。这样做的一种直接方法是在
x
的值上循环:

y <- NULL
for (xx in x) {
    q <- dbSendQuery(con , "select mypgfunc( $1 , $2 )")
    dbBind(q , c(xx, a))
    if (is.null(y)) {
        y <- dbFetch(q)
    } else {
        y <- rbind(y, dbFetch(q))
    }        
    dbClearResult(q)
}

y我做了更多的研究,找到了另一个避免for循环的解决方案

我只需将myWrapper函数更改为以下代码:

myWrapper <- function(x , a) {
  con <- dbConnect(drv = RPostgres::Postgres() , dbname='mydb')
  
  a <- rep(a , length(x))
  q <- dbSendQuery(con , "select mypgfunc( $1::numeric , $2::numeric )")
  dbBind(q , list(x,a))
  y <- dbFetch(q)
  dbClearResult(q)
  
  dbDisconnect(con)
  
  return(y[,1])
}
myWrapper
y <- NULL
for (xx in x) {
    q <- dbSendQuery(con , "select mypgfunc( $1 , $2 )")
    dbBind(q , c(xx, a))
    if (is.null(y)) {
        y <- dbFetch(q)
    } else {
        y <- rbind(y, dbFetch(q))
    }        
    dbClearResult(q)
}
myWrapper <- function(x , a) {
  con <- dbConnect(drv = RPostgres::Postgres() , dbname='mydb')
  
  a <- rep(a , length(x))
  q <- dbSendQuery(con , "select mypgfunc( $1::numeric , $2::numeric )")
  dbBind(q , list(x,a))
  y <- dbFetch(q)
  dbClearResult(q)
  
  dbDisconnect(con)
  
  return(y[,1])
}