按城市/地区分组 JSON 坐标

Posted

技术标签:

【中文标题】按城市/地区分组 JSON 坐标【英文标题】:Group JSON Coordinates by City / Area 【发布时间】:2018-12-27 17:48:38 【问题描述】:

我有一个客户列表,其中包含一些销售数据及其坐标。我想在地图上显示它,但我不想拥有 10,000 个标记,我想将它们分组以获得不同半径的圆圈,具体取决于该地区的客户数量。这是我的数据集的示例:

[
  
    "latitude": "44.141638",
    "longitude": "-149.935598",
    "family_size": 1
  ,
  
    "latitude": "44.141314",
    "longitude": "-149.935556",
    "family_size": 3
  ,
  
    "latitude": "44.200873",
    "longitude": "-130.025254",
    "family_size": 2
  ,
  
    "latitude": "45.202873",
    "longitude": "-131.0243 54",
    "family_size": 2
  
]

我的想法是从每条记录中获取纬度和经度,并使用滑块/缩放级别组合调整小数点的数量,以便在缩小时可以看到它们成组。例如,当您缩小前 2 条记录时,将转换为:

  
    "latitude": "44.141",
    "longitude": "-149.935",
    "family_size": 3
  ,
  
    "latitude": "44.141",
    "longitude": "-149.935",
    "family_size": 1
  

然后我将半径定义为匹配坐标处的家庭成员数,因此总共为 4。

我已经看到了一种获取数组中唯一值计数的方法,但是当您需要匹配 2 个键/值对时如何获取计数?

传入的数据有大约 10,000 条记录,我希望将数据加载到浏览器并让客户端 PC 处理工作负载,而不是尝试全部使用 php/AJAX 来完成,因为我希望他们能够操作什么按日期、性别、收入显示...

更新

我有一种在小范围内工作的方法,但在扩大到许多记录时会以两种方式失败。首先是由于某种原因计数器会下降很多,其次是因为我担心以这种方式循环非常低效。

这是我所拥有的:

function GroupXY(arr) 
    var a = [],b = [],prev;

    arr.sort();

    for (var i = 0; i < arr.length; i++) 
        if (arr[i].latitude !== prev) 
            a.push(arr[i]);
        
        prev = arr[i].latitude;
    

    var c = [], d = [], prevL;

    for (var L = 0; L < arr.length; L++) 
        if (arr[L].longitude !== prevL) 
            c.push(arr[L]);
        
        prevL = arr[L].longitude;
    

    var matches = ,
        counter = [];

    for (var M = 0; M < arr.length; M++) 
        for (var A = 0; A < a.length; A++) 
            if (isEmpty(matches[a[A].latitude])) 
                matches[a[A].latitude] = ;
            
            var uniqueLatitude = a[A].latitude;
            if (arr[M].latitude == uniqueLatitude) 

                for (var C = 0; C < c.length; C++) 
                    var thisLongitude = c[C].longitude;
                    if (arr[M].longitude === thisLongitude && arr[M].latitude == c[C].latitude) 
                        //Full Match

                        if (isEmpty(matches[uniqueLatitude])) 
                            matches[uniqueLatitude][thisLongitude] = arr[M].family_size;
                         else 
                            matches[uniqueLatitude][thisLongitude] = matches[uniqueLatitude][thisLongitude] + arr[M].family_size;

                        

                     else 
                    
                
             else 
        
    

这是一个带有数据的 jsfiddle:https://jsfiddle.net/xpvt214o/450422/

虽然它一次在 5 条记录上表现良好,但当我尝试向它提供 5000 条记录时,它完全冻结了浏览器并开始给出疯狂的 family_size 结果,例如 40,000。

似乎对 XY 坐标进行分组是 javascript 擅长的,并且内置了一些东西,因此可以在编译代码而不是脚本中处理它。

【问题讨论】:

如果你用正方形而不是圆形,它只是四舍五入:var x = Math.floor(latitude / 10);,然后用相同的 x 和 y 分组。 循环遍历数据集,进行条件检查是否通过,然后更新计数器。 这就是我的想法,也是使用舍入,但我不知道如何将它们与 2 个唯一值分组。 亚当,我可以按照你说的循环遍历它,但似乎我必须解析它 3 次并且多次解析 1MB 的数据效率低下。我不确定javascript中是否有任何内置方式来匹配坐标 developers.google.com/maps/documentation/javascript/… 【参考方案1】:

看到这个:- 在 Maps 初始化并且标记数组调用 this 之后

see this Example With Whole Code

var markerCluster = new MarkerClusterer(map, markers,
        imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m');
  

【讨论】:

感谢 D-John,这将是一个很好的方法,除非我使用的是 OpenStreetMap 并且需要一些精细控制,以便我可以在标记中显示我想要的内容。标记将显示销售额、性别、家庭规模等的平均值。因此,对于一般需求来说,这是一个很好的解决方案,但我需要一些更具体的东西。【参考方案2】:

重写了几次之后,因为速度问题,这就是我想出的。由于我拥有的记录数量,我觉得过滤一次以获得独特的纬度会很有帮助。

function filterArray(incomingArray)
  var unique = ;
  var distinct = [];
  for( var i in incomingArray )
   if( typeof(unique[incomingArray[i][0]]) == "undefined")
    distinct.push([incomingArray[i][0],]);
   
   unique[incomingArray[i][0]] = 0;
  
  return distinct;

function GroupCoords(incomingArray, rounding) 
  var xy = [];
  for(var i =0; i<incomingArray.length; i++)
    var latitude = parseFloat(incomingArray[i].latitude).toFixed(rounding);
    xy.push([latitude]);
  

  var locations =filterArray(xy);

  for(var i =0; i<incomingArray.length; i++)
    var latitude = parseFloat(incomingArray[i].latitude).toFixed(rounding);
    var longitude = parseFloat(incomingArray[i].longitude).toFixed(rounding);
    var familySize = incomingArray[i].family_size;

    for(var X =0; X<locations.length; X++)
      if(latitude==locations[X][0])
        if(!locations[X][longitude])
          locations[X][longitude]=familySize;
          counter = counter + familySize;
        else
          locations[X][longitude] = locations[X][longitude] + familySize;
          counter = counter + familySize;

              
      
    
  
  return locations;


console.log(GroupCoords(data, 3));

将返回一个数组,例如:

[
  [
    "30.557", //latitude
    
      "-87.260": 1 // longitude : family_size
    
  ],
  [
    "30.570",//latitude
    
      "-87.260": 1 // longitude : family_size
    ,
    
      "-87.340": 4 // longitude : family_size
    
  ]
]

每个纬度可以有多个经度,其中可以包含您要存储的任何额外信息。通过将坐标四舍五入到 3,它几乎立即将大约 6000 条记录减少到大约 750 条,这将允许我使用滑块来调整分组大小。

【讨论】:

以上是关于按城市/地区分组 JSON 坐标的主要内容,如果未能解决你的问题,请参考以下文章

json JSON中按地理坐标划分的1000个美国最大城市

如何制作动态层分组报表

地理 IP 和国家/地区/城市数据库

bigquery row_number 根据特定字段按某些行分组

将完整地址转换为按城市、地区、邮政编码等分隔的地址

如何在本地反应中获取坐标并按城市名称放置标记?