将列表/数组作为参数/返回类型传递并返回给 Redshift 中的 UDF

Posted

技术标签:

【中文标题】将列表/数组作为参数/返回类型传递并返回给 Redshift 中的 UDF【英文标题】:Passing & returning a list/array as a parameter/ return type to a UDF in Redshift 【发布时间】:2016-02-04 03:28:33 【问题描述】:

我有一堆指标消耗一列的整个浮点值列表(想想一系列订单值,我在上面做一些异常值分析,因此需要整个值数组)。

我可以将整个列表作为参数传递吗?如果我完全在 python 中执行此操作,那将是太多的数据处理。想法?

# Redshift UDF - the red part is invalid signature & needs a fill 
create function Median_absolute_deviation(y <Pass a list, but how? >,threshold float) 

--INPUTS: 
--a list of order values, -- a threshold
 RETURNS <return a list, but how? > 

STABLE 
AS $
    import numpy as np

    m = np.median(y)
    abs_dev = np.abs(y - m)
    left_mad = np.median(abs_dev[y<=m])
    right_mad = np.median(abs_dev[y>=m])
    y_mad = np.zeros(len(y))
    y_mad[y < m] = left_mad
    y_mad[y > m] = right_mad
    modified_z_score = 0.6745 * abs_dev / y_mad
    modified_z_score[y == m] = 0
    return modified_z_score > threshold

$LANGUAGE plpythonu

    我可以从另一个函数传递m = np.median(y)(使用数据库上的 select 语句)-但再次计算 abs_dev & left_mad & right_mad 需要整个系列。

    我可以在这里使用anyelement 数据类型吗? AWS 参考:http://docs.aws.amazon.com/redshift/latest/dg/udf-data-types.html

这是我尝试过的。另外,如果标志为“0”,我想返回该列的值 - 但我想我可以在第二遍时做到这一点?

create or replace function Median_absolute_deviation(y anyelement ,thresh int) 
--INPUTS: 
--a list of order values, -- a threshold
-- I tried both float &  anyelement return type, but same error
RETURNS float 

 --OUTPUT: 
 -- returns the value of order amount if not outlier, else returns 0

STABLE 
AS $$
    import numpy as np

    m = np.median(y)
    abs_dev = np.abs(y - m)
    left_mad = np.median(abs_dev[y<=m])
    right_mad = np.median(abs_dev[y>=m])
    y_mad = np.zeros(len(y))
    y_mad[y < m] = left_mad
    y_mad[y > m] = right_mad
    modified_z_score = 0.6745 * abs_dev / y_mad
    modified_z_score[y == m] = 0
    flag= 1 if (modified_z_score > thresh ) else 0

    return flag

$$LANGUAGE plpythonu
select Median_absolute_deviation(price,3)  from my_table where price >0 limit 5; 
An error occurred when executing the SQL command:
select Median_absolute_deviation(price,3)  from my_table where price >0 limit 5

ERROR: IndexError: invalid index to scalar variable.. Please look at svl_udf_log for more information
  Detail: 
  -----------------------------------------------
  error:  IndexError: invalid index to scalar variable.. Please look at svl_udf_log for more information
  code:      10000
  context:   UDF
  query:     47544645
  location:  udf_client.cpp:298
  process:   query6_41 [pid=24744]
  -----------------------------------------------

Execution time: 0.73s

1 statement failed.

我的最终目标是使用通过 UDF(最终目标)进行的这些计算来填充画面视图 - 所以我需要一些可以与画面交互并使用函数即时进行计算的东西。 建议?

【问题讨论】:

不能用内置函数(docs.aws.amazon.com/redshift/latest/dg/Math_functions.html)吗? @Guy 您是否建议在此 python 函数中使用 AWS 内置函数,而不是 python numpy 函数(用于中值、std_dev 等) - 或者只是基于子构建一个聚合函数聚合函数上的函数。比如,从 my_table 等中选择 abs(price-median(price)) 作为 abs_dev。 Redshift 有很多强大的分析功能,您可以直接在查询中使用。 UDF 应该用于扩展内置函数,它们会更慢、容易出错且更复杂。 【参考方案1】:

Redshift 暂时只支持标量 UDF,这意味着您基本上不能将列表作为参数传递。

话虽如此,您可以发挥创意,将其作为用特殊字符分隔的数字字符串传递,然后将其重新转换为 udf 中的列表,例如: list = [1, 2, 3.5] 可以作为 string_list = "1|2|3.5"

为此,您需要预先确定数字的精度和列表的最大大小,以便定义适当长度的 varchar。 这不是最佳做法,但它会起作用。

【讨论】:

以上是关于将列表/数组作为参数/返回类型传递并返回给 Redshift 中的 UDF的主要内容,如果未能解决你的问题,请参考以下文章

将 numpy 数组传递给 c++ 函数并返回 numpy 数组作为输出的最有效方法是啥?

传递数组作为参数以返回所有匹配元素的行

php 组织各州的县名单。返回任何状态作为数组作为参数传递的县的列表

数组名作函数参数时,实参与形参变量之间的数据传递是?

数组作为方法参数- 数组作为方法返回值

如何编写一个将字符串列表作为参数的函数[重复]