2016-11-27 143 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〜列不是太大),做加盟。这可能是最长的部分。

然后,我将采取两个数组,并计算它们之间的余弦距离

相关问题