Python:总结包含浮点值的猪元组

时间:2016-04-07 18:41:04

标签: python tuples apache-pig

我对Pig / Python很新,需要帮助。试图编写一个协调财务数据的Pig脚本。使用的参数遵循类似(grand_tot,x1,x2,... xn)的语法,这意味着第一个值应该等于剩余值的总和。

我不知道如何单独使用Pig来实现这一目标,所以我一直在尝试编写Python UDF。猪将元组传递给Python;如果x1:xn的总和等于grand_tot,那么Python应该返回一个" 1" to Pig表示数字匹配,否则返回" 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_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'

我尝试过很多尝试将数组值转换为数字并转换为float的东西,以便我可以求和,但没有成功。

任何想法???谢谢你的期待!

2 个答案:

答案 0 :(得分:1)

你可以在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;

答案 1 :(得分:0)

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个异常。阅读 断言要学习,哪个项目正在制造麻烦。

无论如何,如果要在第一个数字等于数组其余部分的总和时返回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:])