Python 两个pyspark数据帧的余弦相似性
我有一个PySpark数据帧df1,看起来像: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
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