Python 两个pyspark数据帧的余弦相似性

Python 两个pyspark数据帧的余弦相似性,python,apache-spark,pyspark,apache-spark-sql,Python,Apache Spark,Pyspark,Apache Spark Sql,我有一个PySpark数据帧df1,看起来像: CustomerID CustomerValue CustomerValue2 12 .17 .08 我有第二个PySpark数据帧,df2 CustomerID CustomerValue CustomerValue 15 .17 .14 16 .40 .43 18 .86 .09

我有一个PySpark数据帧df1,看起来像:

CustomerID  CustomerValue CustomerValue2 
12          .17           .08
我有第二个PySpark数据帧,df2

 CustomerID  CustomerValue CustomerValue
 15          .17           .14
 16          .40           .43
 18          .86           .09
我想计算两个数据帧的余弦相似性。吃点类似的东西

 CustomerID  CustomerID   CosineCustVal CosineCustVal
 15          12           1            .90
 16          12           .45          .67
 18          12           .8           .04

只能计算两个向量的余弦相似性,不能计算两个数字的余弦相似性。也就是说,如果称为CustomerValue的列是向量的不同组成部分,该向量表示要获得两个客户之间相似性的特征,则可以通过转置数据帧,然后对CUATomerValue进行联接来实现

转换可以通过分解完成(有关转换数据帧的更多详细信息):

其中
dft1
dft2
表示转置的数据帧。转换后,可以在列名上连接它们:

dft2 = (dft2.withColumnRenamed('CustomerID', 'CustomerID2')
        .withColumnRenamed('column_value', 'column_value2')
       )
cosine = (dft1.join(dft2, dft1.column_name = dft2.column_name)
          .groupBy('CustomerID' , 'CustomerID2')
          .agg(F.sum(F.column('column_value')*F.column('column_value2')).alias('cosine_similarity'))
         )
现在在
cosine
中有三列:来自第一个和第二个数据帧的CustomerID和cosine相似度(前提是先对值进行了规范化)。这有一个优点,即对于具有非零相似性的CustomerID对,您只有行(在某些CustomerID为零值的情况下)。例如:

df1:

df2:

余弦:

CustomID CustomID2 cosine_similarity
12       15        .0401
12       16        .1024
12       18        .1534
当然,这些并不是真正的余弦相似性,您需要首先规范化这些值。您可以通过以下方式对组执行此操作:

(df.groupBy('CustomerID')
 .agg(F.sqrt(F.sum(F.column('column_value')*F.column('column_value'))).alias('norm'))
 .select('CustomerID', F.column('column_name'), (F.column('column_value')/F.column('norm')).alias('column_value_norm'))
)
规范化列后,余弦相似性如下所示:

CustomID CustomID2 cosine_similarity
12       15        .970
12       16        .928
12       18        .945

较大的相似性值是由于低维度(仅两个组件)。

您尝试过什么吗?是的,很不幸,但它不能工作。我认为的另一个解决方案是转换列表中的第一个df并采用余弦相似性,但我希望避免这种方式第一个数据帧只有一行?另外,这是一个公共列,因为
CustomerID
没有任何公共值,所以您决定将这两个列合并在一起。是的,它只有一行。问题是,我不想加入这两个dfs,因为实际上它们没有相同的CustomerID@mayankagrawalife。如果它只有一行,最好在列表或类似结构中收集它,然后进行计算。无需为单行创建spark数据帧。
CustomID CustomID2 cosine_similarity
12       15        .0401
12       16        .1024
12       18        .1534
(df.groupBy('CustomerID')
 .agg(F.sqrt(F.sum(F.column('column_value')*F.column('column_value'))).alias('norm'))
 .select('CustomerID', F.column('column_name'), (F.column('column_value')/F.column('norm')).alias('column_value_norm'))
)
CustomID CustomID2 cosine_similarity
12       15        .970
12       16        .928
12       18        .945