scala - 有效计算集合元素之间的harsine距离
问题描述
我有两个系列。每个集合由包含纬度、经度和历元的集合组成。
val arr1= Seq(Seq(34.464, -115.341,1486220267.0), Seq(34.473,
-115.452,1486227821.0), Seq(35.572, -116.945,1486217300.0),
Seq(37.843, -115.874,1486348520.0),Seq(35.874, -115.014,1486349803.0),
Seq(34.345, -116,924, 1486342752.0) )
val arr2= Seq(Seq(35.573, -116.945,1486217300.0 ),Seq(34.853,
-114.983,1486347321.0 ) )
我想确定这两个阵列在 0.5 英里内有多少次并且具有相同的时代。我有两个功能
def haversineDistance_single(pointA: (Double, Double), pointB: (Double, Double)): Double = {
val deltaLat = math.toRadians(pointB._1 - pointA._1)
val deltaLong = math.toRadians(pointB._2 - pointA._2)
val a = math.pow(math.sin(deltaLat / 2), 2) + math.cos(math.toRadians(pointA._1)) * math.cos(math.toRadians(pointB._1)) * math.pow(math.sin(deltaLong / 2), 2)
val greatCircleDistance = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
3958.761 * greatCircleDistance
}
def location_time(col_2:Seq[Seq[Double]], col_1:Seq[Seq[Double]]): Int={
val arr=col_1.map(x=> col_2.filter(y=> (haversineDistance_single((y(0), y(1)), (x(0),x(1)))<=.5) &
(math.abs(y(2)-x(2))<=0)).flatten).filter(x=> x.length>0)
arr.length
}
location_time(arr1,arr2) =1
我的实际收藏非常大,有没有比我的 location_time 函数更有效的方法来计算它。
解决方案
我会考虑修改location_time
:
def location_time(col_mobile: Seq[Seq[Double]], col_laptop: Seq[Seq[Double]]): Int = {
val arr = col_laptop.map( x => col_mobile.filter( y =>
(haversineDistance_single((y(0), y(1)), (x(0), x(1))) <= .5) & (math.abs(y(2) - x(2)) <= 0)
).flatten
).filter(x => x.length > 0)
arr.length
}
到:
def location_time(col_mobile: Seq[Seq[Double]], col_laptop: Seq[Seq[Double]]): Int = {
val arr = col_laptop.flatMap( x => col_mobile.filter( y =>
((math.abs(y(2) - x(2)) <= 0 && haversineDistance_single((y(0), y(1)), (x(0), x(1))) <= .5))
)
)
arr.length
}
所做的更改:
修订
col_mobile.filter(y => ...)
自:filter(_ => costlyCond1 & lessCostlyCond2)
到:
filter(_ => lessCostlyCond2 && costlyCond1)
假设
haversineDistance_single
运行成本高于math.abs
,替换&
为&&
(参见& 与 &&之间的区别)并math.abs
首先测试可能有助于过滤性能。简化
map/filter/flatten/filter
使用flatMap
,替换:col_laptop.map(x => col_mobile.filter(y => ...).flatten).filter(_.length > 0)
和:
col_laptop.flatMap( x => col_mobile.filter( y => ... ))
如果您可以访问 Apache Spark 集群,请考虑将您的集合(如果它们真的很大)转换为 RDD 以使用与上述类似的转换进行计算。
推荐阅读
- java - `ConnectException` 的 TCP 错误是什么?
- node.js - 如何更新数组中的特定对象?
- ios - 检查用户的位置是否在印度
- node.js - 每当捕获错误或控制台错误出现并且服务器在本地主机或生产端(heroku)停止时,如何在 UI 上显示错误警报?
- reactjs - AntDesign 表单或 React Hook 表单
- checkbox - 复选框不启用字段淘汰赛
- office-js - 是否可以使用 MS PowerPoint 插件选择/更新形状/图标/图像属性?
- ios - StoreKitTest:请求产品错误域=ASDErrorDomain 代码=950“未处理的异常”
- node.js - “GeometryDataType”类型中不存在坐标
- r - 在r上的数据框中减去日期列