scala - 使用数据框 Scala Spark 计算余弦相似度
问题描述
我有一个这种形式的数据框:
+-------+-------+------------------+-------+----+
|userId1|movieId| rat1|userId2|rat2|
+-------+-------+------------------+-------+----+
| 1| 1| 1.0| 2| 1.0|
| 1| 2| 1.0| 2| 2.0|
| 1| 3| 2.0| 2| 3.0|
| 2| 1| 1.0| 3| 0.0|
| 2| 2| 2.0| 3| 0.0|
| 2| 3| 3.0| 3| 0.0|
| 3| 1| 0.0| 1| 1.0|
| 3| 2| 0.0| 1| 1.0|
....
其中rat1 和rat2 是user1 和user2 的评分。我想要的是计算两个用户之间的余弦相似度,我的想法是从这个数据帧中提取数组,然后计算余弦相似度,例如:
arrayUser1 = (1,1,2)
arrayUser2 = (1,2,3)
arrayUser3 = (0,0,0)
问题是我不知道如何提取这些数组,有人有解决方案吗?或者以更好的方式计算相似度的技巧?
解决方案
您可以先将rat1和rat2相乘,然后按userId1和userId2分组,然后将乘积相加:
df.show
+-------+-------+----+-------+----+
|userId1|movieId|rat1|userId2|rat2|
+-------+-------+----+-------+----+
| 1| 1| 1.0| 2| 1.0|
| 1| 2| 1.0| 2| 2.0|
| 1| 3| 2.0| 2| 3.0|
| 2| 1| 1.0| 3| 0.0|
| 2| 2| 2.0| 3| 0.0|
| 2| 3| 3.0| 3| 0.0|
| 3| 1| 0.0| 1| 1.0|
| 3| 2| 0.0| 1| 1.0|
| 3| 3| 0.0| 1| 2.0|
+-------+-------+----+-------+----+
val cos_sim = df.withColumn(
"rat1", // normalize rat1
coalesce(
$"rat1" / sqrt(sum($"rat1" * $"rat1").over(Window.partitionBy("userId1"))),
lit(0)
)
).withColumn(
"rat2", // normalize rat2
coalesce(
$"rat2" / sqrt(sum($"rat2" * $"rat2").over(Window.partitionBy("userId2"))),
lit(0)
)
).withColumn(
"rat1_times_rat2",
$"rat1" * $"rat2"
).groupBy("userId1", "userId2").agg(sum("rat1_times_rat2").alias("cos_sim"))
cos_sim.show
+-------+-------+-----------------+
|userId1|userId2| cos_sim|
+-------+-------+-----------------+
| 3| 1| 0.0|
| 2| 3| 0.0|
| 1| 2|0.981980506061966|
+-------+-------+-----------------+
推荐阅读
- python - 解析仅在将 selenium python 指向它后才变为活动的链接
- emacs - 无法在 GNU Emacs 27.2 中一起启动.el 服务器
- python - int('10000000000000000000000000000001',2) 不返回负值
- typeerror - TypeError: 'value' 必须是 str 或 bytes 的实例,而不是 NoneType
- python - 在 Raspbian Buster 上守护 Python 脚本
- regex - 如何 awk 或 grep 过滤前 n 个字符中至少有 1 个数字的字符串?
- python-3.x - python id() 函数实现
- reactjs - 获取请求在无服务器堆栈中返回未定义
- reactjs - 钩子和组件重新渲染
- java - 检测 JUnit 中的 RetentionPolicy.CLASS 注释