python:对包含浮点值的pig元组求和

cczfrluj  于 2021-06-21  发布在  Pig
关注(0)|答案(2)|浏览(389)

我对pig/python还比较陌生,需要帮助。试图编写一个pig脚本来协调财务数据。使用的参数遵循如下语法(grand_tot,x1,x2,。。。xn),意思是第一个值应该等于剩余值的和。
我不知道如何单独使用pig来实现这一点,所以我一直在尝试编写python自定义项。pig将一个元组传递给python;如果x1:xn的和等于grand_tot,那么python应该向pig返回一个“1”来表示数字匹配,否则返回一个“0”。
到目前为止,我掌握的情况如下:

register 'myudf.py' using jython as myfuncs; 
A = LOAD '$file_nm' USING PigStorage(',') AS (grand_tot,west_region,east_region,prod_line_a,prod_line_b, prod_line_c, prod_line_d); 
A1 = GROUP A ALL; 
B = FOREACH A1 GENERATE TOTUPLE($recon1) as flds; 
C = FOREACH B GENERATE myfuncs.isReconciled(flds) AS res;
DUMP C;

$recon1作为参数传递,定义为:

grand_tot, west_region, east_region

稍后我将传递$recon2作为:

grand_tot, prod_line_a, prod_line_b, prod_line_c, prod_line_d

数据的示例行(以$file\u nm为单位)如下所示:

grand_tot,west_region,east_region,prod_line_a,prod_line_b, prod_line_c, prod_line_d
10000,4500,5500,900,2200,450,3700,2750
12500,7500,5000,3180,2770,300,3950,2300
9900,7425,2475,1320,460,3070,4630,1740

最后。。。下面是我尝试使用python udf代码所做的:

@outputSchema("result")
def isReconciled(arrTuple):
    arrTemp = []
    arrNew = []
    string1 = ""
    result = 0
    ## the first element of the Tuple should be the sum of remaining values
    varGrandTot = arrTuple[0]
    ## create a new array with the remaining Tuple values
    arrTemp = arrTuple[1:]

    for item in arrTuple:
        arrNew.append(item)

    ## sum the second to the nth values
    varSum = sum(arrNew)

    ## if the first value in the tuple equals the sum of all remaining values
    if varGrandTot = varSum then:
        #reconciled to the penny
        result = 1
    else:
        result = 0

    return result

我收到的错误消息是:不支持+:“int”和“array.array”的操作数类型
我尝试了很多方法,试图将数组值转换为数字,然后转换为浮点值,这样我就可以求和了,但是没有成功。
有什么想法吗???感谢您的光临!

piah890a

piah890a1#

很可能,你的 arrTuple 不是数字数组,但某些项是数组。
要检查它,请通过添加一些检查来修改代码:

@outputSchema("result")
def isReconciled(arrTuple):
    # some checks
    tmpl = "Item # {i} shall be a number (has value {itm} of type {tp})"
    for i, num in enumerate(arrTuple):
        msg = templ.format(i=i, itm=itm, tp=type(itm))
        assert isinstance(arrTuple[0], (int, long, float)), msg
    # end of checks

    arrTemp = []
    arrNew = []
    string1 = ""
    result = 0
    ## the first element of the Tuple should be the sum of remaining values
    varGrandTot = arrTuple[0]
    ## create a new array with the remaining Tuple values
    arrTemp = arrTuple[1:]

    for item in arrTuple:
        arrNew.append(item)

    ## sum the second to the nth values
    varSum = sum(arrNew)

    ## if the first value in the tuple equals the sum of all remaining values
    if varGrandTot = varSum then:
        #reconciled to the penny
        result = 1
    else:
        result = 0

    return result

很有可能,它会抛出一个 AssertionFailed 其中一项出现异常。阅读Assert消息以了解是哪一项造成了问题。
无论如何,如果要在第一个数字等于数组其余部分的和时返回0或1,则以下操作也可以:

@outputSchema("result")
def isReconciled(arrTuple):
    if arrTuple[0] == sum(arrTuple[1:]):
        return 1
    else:
        return 0

以防万一,你会很高兴 True 而不是1和 False 而不是0:

@outputSchema("result")
def isReconciled(arrTuple):
    return arrTuple[0] == sum(arrTuple[1:])
eqfvzcg8

eqfvzcg82#

你可以在Pig身上做这个。
首先,在模式中指定数据类型。pigstorage将使用bytearray作为默认数据类型。因此,python脚本抛出错误。看起来示例数据有int,但在您的问题中,您提到了float。
其次,添加从第二个字段开始的字段或您选择的字段。
第三,使用bincond操作符检查第一个字段的值和。

A = LOAD '$file_nm' USING PigStorage(',') AS (grand_tot:float,west_region:float,east_region:float,prod_line_a:float,prod_line_b:float, prod_line_c:float, prod_line_d:float); 
A1 = FOREACH A GENERATE grand_tot,SUM(TOBAG(prod_line_a,prod_line_b,prod_line_c,prod_line_d)) as SUM_ALL; 
B = FOREACH A1 GENERATE (grand_tot == SUM_ALL ? 1 : 0); 
DUMP B;

相关问题