在ggplot2中使用geom_function调用一个用postgreSQL plr编写的函数
Using geom_function in ggplot2 to call a function written in postgreSQL plr
我很难从 R 脚本调用 postgreSQL 中的 plr 函数并在 ggplot2 中使用它 - geom_function。以下示例已极度简化,但希望能说明问题。
假设我有以下 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_function 我想,我可以编写以下简单的包装函数来执行查询(我使用 rpostgres 包):
myWrapper <- function(x , a) {
con <- dbConnect(drv = RPostgres::Postgres() , dbname='mydb')
q <- dbSendQuery(con , "select mypgfunc( , )")
dbBind(q , c(x,a))
y <- dbFetch(q)
dbClearResult(q)
dbDisconnect(con)
return(y)
}
但是如果我现在从 ggplot 调用这个函数,我会收到以下警告消息和一个空图:
Computation failed in stat_function()
:
Query requires 2 params; 102 supplied.
ggplot 代码如下所示:
ggplot() +
geom_function(fun = myWrapper , args = list(a = 5))
如果我改为在 R 中编写 plr 函数并从 geom_function 调用它,一切正常。
如果我直接调用 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 无法绘制只有 1 个点的线)。
因此,基本上,您需要对向量的每个值进行单独查询 x
。一种直接的方法是遍历 x
:
的值
y <- NULL
for (xx in x) {
q <- dbSendQuery(con , "select mypgfunc( , )")
dbBind(q , c(xx, a))
if (is.null(y)) {
y <- dbFetch(q)
} else {
y <- rbind(y, dbFetch(q))
}
dbClearResult(q)
}
就像我说的,我没有在 R 中使用 SQL。所以我相信有更聪明的方法可以做到这一点,你不需要调用丑陋的 for
循环(也不确定你是否需要循环内的 dbSendQuery
)。
我做了更多研究并找到了另一个避免 for 循环的解决方案。
我只需要将 myWrapper 函数更改为以下代码:
myWrapper <- function(x , a) {
con <- dbConnect(drv = RPostgres::Postgres() , dbname='mydb')
a <- rep(a , length(x))
q <- dbSendQuery(con , "select mypgfunc( ::numeric , ::numeric )")
dbBind(q , list(x,a))
y <- dbFetch(q)
dbClearResult(q)
dbDisconnect(con)
return(y[,1])
}
我很难从 R 脚本调用 postgreSQL 中的 plr 函数并在 ggplot2 中使用它 - geom_function。以下示例已极度简化,但希望能说明问题。
假设我有以下 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_function 我想,我可以编写以下简单的包装函数来执行查询(我使用 rpostgres 包):
myWrapper <- function(x , a) {
con <- dbConnect(drv = RPostgres::Postgres() , dbname='mydb')
q <- dbSendQuery(con , "select mypgfunc( , )")
dbBind(q , c(x,a))
y <- dbFetch(q)
dbClearResult(q)
dbDisconnect(con)
return(y)
}
但是如果我现在从 ggplot 调用这个函数,我会收到以下警告消息和一个空图:
Computation failed in
stat_function()
: Query requires 2 params; 102 supplied.
ggplot 代码如下所示:
ggplot() +
geom_function(fun = myWrapper , args = list(a = 5))
如果我改为在 R 中编写 plr 函数并从 geom_function 调用它,一切正常。 如果我直接调用 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 无法绘制只有 1 个点的线)。
因此,基本上,您需要对向量的每个值进行单独查询 x
。一种直接的方法是遍历 x
:
y <- NULL
for (xx in x) {
q <- dbSendQuery(con , "select mypgfunc( , )")
dbBind(q , c(xx, a))
if (is.null(y)) {
y <- dbFetch(q)
} else {
y <- rbind(y, dbFetch(q))
}
dbClearResult(q)
}
就像我说的,我没有在 R 中使用 SQL。所以我相信有更聪明的方法可以做到这一点,你不需要调用丑陋的 for
循环(也不确定你是否需要循环内的 dbSendQuery
)。
我做了更多研究并找到了另一个避免 for 循环的解决方案。
我只需要将 myWrapper 函数更改为以下代码:
myWrapper <- function(x , a) {
con <- dbConnect(drv = RPostgres::Postgres() , dbname='mydb')
a <- rep(a , length(x))
q <- dbSendQuery(con , "select mypgfunc( ::numeric , ::numeric )")
dbBind(q , list(x,a))
y <- dbFetch(q)
dbClearResult(q)
dbDisconnect(con)
return(y[,1])
}