2016-03-03 111 views
2

值操作我有這樣的RDD:Pyspark:基於類型

[('a', ('H', 1)), ('b', (('H', 41), ('S', 1)))] 

使按鍵可以有一個tupletuples一個tuple的值。這來自reduceByKey。 我需要執行一個簡單的操作:將S的計數除以(H + S)的計數。 當S不存在時,就像在第一個項目的情況下,我將不得不返回0. 問題是從第二個(tuple的兩個tuples)中分離第一個案例(單個tuple),以便我知道如何在map中運作。

我將如何進行?

+0

你是如何得到這樣的數據呢?它是一種具有特定意義的層次結構嗎?如果沒有,我會更有意義的執行上游一致的整形器。 Python自3.4以來提供了基本的調度機制,但這些都很淺。 – zero323

回答

1

一般來說它會更有意義,以解決這一問題的上游,但你可以嘗試例如是這樣的:

from operator import truediv 

def f(vs): 
    try: 
     d = dict(vs) 
    except ValueError: 
     d = dict([vs]) 

    s = sum(d.values()) 
    return truediv(d.get("S", 0), s) if s else float('nan') 

rdd = sc.parallelize([('a', ('H', 1)), ('b', (('H', 41), ('S', 1)))]) 
rdd.mapValues(f).collect() 

## [('a', 0.0), ('b', 0.023809523809523808)] 

另外,如果你不介意的外部依賴性,你可以嘗試使用multipledispatch

from multipledispatch import dispatch 

@dispatch(tuple, tuple) 
def f(h, s): 
    try: 
     return truediv(s[1], h[1] + s[1]) 
    except ZeroDivisionError: 
     return float('nan') 

@dispatch(str, int) 
def f(x, y): 
    return 0.0 

rdd.mapValues(lambda args: f(*args)).collect() 
## [('a', 0.0), ('b', 0.023809523809523808)] 
+0

兩者之間是否存在性能差異? –

+1

我喜歡調度方法,它確實應該隱藏「isinstance」的醜陋之處。但它需要相對複雜的代碼。如果走上一條快樂的道路(不要輸入'除了'阻止第一個應該更快)。異常處理相當昂貴,但我希望攤銷成本會更高。一般來說,我會真正解決這個問題,並提供可以直接使用的輸入。 – zero323