2016-04-07 17 views
0

Pig/Python için oldukça yeni ve yardıma ihtiyacım var. Finansal verileri uzlaştıran bir Pig Script yazmaya çalışıyorum. Kullanılan parametreler (grand_tot, x1, x2, ... xn) gibi bir sözdizimini takip eder, yani ilk değerin kalan değerlerin toplamına eşit olması gerektiği anlamına gelir.Python: Float değerlerini içeren bir domuz tuplesi toplanması

Tek başına Pig kullanarak bunu gerçekleştirmenin bir yolunu bilmiyorum, bu yüzden bir Python UDF yazmayı deniyorum. Domuz Python'a bir tuple geçer; x1: xn toplamı grand_tot'a eşitse, Python sayıların eşleştiğini göstermek için Pig'a "1" döndürmelidir, aksi takdirde "0" değerini döndürür. Daha sonra $ recon2 olarak geçecek

grand_tot, west_region, east_region 

:

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 parametre olarak geçti ve şöyle tanımlanır: Burada

Bugüne kadar ne var:

grand_tot, prod_line_a, prod_line_b, prod_line_c, prod_line_d 

Örnek satır ($ file_nm cinsinden) benziyor veri:

@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 

aldığım hata iletisi şudur: Son olarak

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 

... işte ben Python UDF kodu ile yapmaya çalışıyorum budur : desteklenmeyen işlenen + için tip (ler): 'int' ve 'array.array'

Ben pek çok şey sayısal içine dizi değerlerini dönüştürmek ve böylece yüzer dönüştürmeye çalışıyor denedim özetleyebilirim, ama hiç başarı göstermeden.

Herhangi bir fikir ??? Baktığın için teşekkürler!

cevap

1

Sen PIG kendisi bunu yapabilirsiniz.

İlk olarak, şemadaki veri türünü belirtin. PigStorage, bytearray'i varsayılan veri türü olarak kullanır. Bu nedenle, python komut dosyanız hata atıyor.Örnek verilerinizin int gibi gözüktüğü ancak sorunuzda float'tan bahsettiniz.

İkincisi, ikinci alandan veya seçtiğiniz alanlardan başlayan alanları ekleyin.

Üçüncü olarak, toplam alan değerini toplam ile kontrol etmek için bin ms operatörünü kullanın.

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; 
+0

Bu, birkaç ayarlamayla çalışır. Python olmadan da performans arttı (bonus). Teşekkürler. – JaneQDoe

+0

@JaneQDoe Cool.Lütfen sorunuzun cevabını cevaplayın –

0

Büyük olasılıkla, arrTuple numaranız bir dizi değil, ancak bazı öğeler bir dizidir.

, kontrol bazı kontrolleri ekleyerek kodunu değiştirmek için:

@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 

Çok muhtemeldir, bu öğelerden birini bir AssertionFailed istisna olacağı. Hangi öğenin sorun çıkardığını öğrenmek için onaylama mesajını okuyun. İlk sayı dizinin kalanı toplamına eşittir eğer 0 veya 1 dönmek istiyorsanız

Neyse, aşağıdaki iş çok:

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

ve durumda, True alma ile mutlu yaşardım yerine 1 ve False yerine 0:

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