2016-11-27 116 views
2

我有兩個數據幀,一個用於用戶配置文件,另一個用於項目配置文件。計算pyspark中兩個數據幀的行之間的距離

df_client = sqlContext.createDataFrame([('c1',0,1,3),('c2',1,0,3)], ['client_id','col1','col2','col3']) 
df_item = sqlContext.createDataFrame([('it1',0,1,3),('it2',1,0,3)], ['item_id','col1','col2','col3']) 

而且我想計算用戶和項目之間的餘弦相似性,並獲得最終的數據幀是這樣的:

df_final.show() 
     client_id item_id distance 
0  c1  it1  0 
1  c1  it2  0.1 
2  c2  it1  0.1 
3  c2  it2  0 

但在現實中有1100萬個用戶,150項和150列。 所以我開發了三個解決方案,但每個解決方案都需要一些時間。

的解決方案的例子:

list_item= df_item.rdd.collect() 

def cosine_distance(v): 

    list_item_distance = [] 

    for row in list_item: 
     distance = round(float(cosine(np.array(v[1:]),np.array(row[1:]))),4) 
     list_item_distance.append((v["client_id"],row["item_id"],distance)) 

    return list_item_distance 

rdd_final = df_client.rdd.map(lambda row: cosine_distance(row)) 

list_final = rdd_final.reduce(lambda x,y: x+y) 

但減少是長期

該問題是否會得到像數據幀的結果呢? 有人有解決方案來快速實現這項工作嗎?

+0

請注意,您的問題基本上可以歸結爲'df_client.rdd.cartesian(df_item.rdd).MAP(拉姆達X:(X [0 ],[],[],[x],[x],x [1] [0],cx(x [0] [1:],x [1] [1:]))) np.round(np.inner(a,b)/(numpy.linalg.norm(a)* numpy.linalg.norm(b)),4)'。這裏的問題是'笛卡爾',它可能會帶來很多網絡流量。 –

回答

0

我會做的第一件事是將列轉換爲數組。由於沒有直接的方法,你可以通過df.create_map(colnames)將列轉換爲地圖,然後選擇一個順序並創建一個udf,將其轉換爲數組。

接下來,我將標誌着東風廣播項目(150線,150〜列不是太大),做加盟。這可能是最長的部分。

然後,我將採取兩個數組,並計算它們之間的餘弦距離