【问题标题】:Implementing pairwise linear distance in Scala在 Scala 中实现成对线性距离
【发布时间】:2019-07-09 04:31:13
【问题描述】:

假设我在 Scala Spark 中有以下 DataFrame,其中年份 year 值是字符串分类表示,但数据中有顺序。

+-----+
|years|
+-----+
|  0-1|
|  1-2|
|  2-5|
| 5-10|
+-----+

我想创建一个结果成对矩阵,表示每对值的“距离”。相同的值被赋予1 的分数,在极端的值被赋予0 例如。 “0-1”和“5-10”。剩余的值用线性模型填充。:

我想要以下预期结果(在 DataFrame 或类似结构中查询一对)

x/y, 0-1,   1-2,  2-5,  5-10,
0-1,  1   , 0.33, 0.67, 0,
1-2,  0.33, 1 ,   0.33, 0.67,
2-5,  0.67, 0.33, 1 ,   0.33,
5-10, 0   , 0.67, 0.33, 1

最后,对于给定的一对years,我想检索distance 值。我想避免对这个解决方案进行硬编码,有更好的方法吗?

【问题讨论】:

  • 不太清楚你想在这里计算什么...你是怎么得到d(1-2, 2-5) = 0的?
  • @AndreyTyukin 感谢您指出这一点——我犯了一个错误,应该是 0.33
  • 那么,你只关心元素的顺序,数值完全被忽略了,对吧?
  • @AndreyTyukin 你是对的!

标签: algorithm scala dataframe linear-regression


【解决方案1】:

只需将您的标签映射到点0 = 0/g, 1/g, 2/g, ... , g/g = 1,其中g 是两个相邻标签之间的间隙数,即标签数减一:

def similarityMatrix[A](xs: List[A]): Map[A, Map[A, Double]] = {
  val numGaps = xs.size - 1
  val positions = xs.zip((0 to numGaps).map(i => i.toDouble / numGaps)).toMap
  def similarity(x: A, y: A) = 1.0 - math.abs(positions(x) - positions(y))
  xs.map(x => (x, xs.map(y => (y, similarity(x, y))).toMap)).toMap
}

你的例子:

val ranges = List("0-1", "1-2", "2-5", "5-10")
val matrix = similarityMatrix(ranges)

for (x <- ranges) {
  for (y <- ranges) {
    printf("%4.2f ", matrix(x)(y))
  }
  println()
}

提供以下嵌套地图:

1.00 0.67 0.33 0.00 
0.67 1.00 0.67 0.33 
0.33 0.67 1.00 0.67 
0.00 0.33 0.67 1.00 

当然适用于任何维度:

1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 0.44 0.38 0.31 0.25 0.19 0.13 0.06 0.00 
0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 0.44 0.38 0.31 0.25 0.19 0.13 0.06 
0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 0.44 0.38 0.31 0.25 0.19 0.13 
0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 0.44 0.38 0.31 0.25 0.19 
0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 0.44 0.38 0.31 0.25 
0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 0.44 0.38 0.31 
0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 0.44 0.38 
0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 0.44 
0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 0.50 
0.44 0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 0.56 
0.38 0.44 0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 0.63 
0.31 0.38 0.44 0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 0.69 
0.25 0.31 0.38 0.44 0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 0.75 
0.19 0.25 0.31 0.38 0.44 0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 0.81 
0.13 0.19 0.25 0.31 0.38 0.44 0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 0.88 
0.06 0.13 0.19 0.25 0.31 0.38 0.44 0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 0.94 
0.00 0.06 0.13 0.19 0.25 0.31 0.38 0.44 0.50 0.56 0.63 0.69 0.75 0.81 0.88 0.94 1.00 

【讨论】:

  • 感谢优雅的解决方案,我太沉迷于使用 DataFrames 以至于忘记使用 Map 等其他数据结构。
  • @Ivan 这个整个矩阵基本上适合我的屏幕(模舍入误差),它很小,所以无论如何将它存储在分布式数据框中是没有意义的。
  • 你是对的。对于一个简单的任务来说似乎有点过头了,再次感谢您的帮助!
  • @Ivan 另一方面,如果你真的想要,那么它会是一个简单的zipWithIndex,然后是map,然后是crossProduct,然后是另一个map。应该也不会太难。
  • 从地图中检索应该比将其存储在分布式 DataFrame 中快得多,我确实需要非常频繁地访问此地图
猜你喜欢
  • 2021-07-03
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 2015-09-22
  • 1970-01-01
  • 2012-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多