zoukankan      html  css  js  c++  java
  • 【原创】大叔案例分享(1)基于地址位置的用户人群定位方案

    背景

    假设一个应用有很多的用户位置信息基础数据,抽象数据格式如下:

    user_id
    date
    time
    address
    province
    city
    district
    latitude
    longitude
    user1 2018-01-01 12:00:00 北京市朝阳区朝阳大悦城 北京 北京 朝阳 1.1 1.2
    ...                

    应用里有一些需要根据地址位置定位用户的需求,抽象问题是任给一块区域找出该区域内所有的user_id,具体如下:

    1. 给定一个经纬度参数以及半径公里数参数,提取该圆范围内所有的user_id;
    2. 给定一个任意多边形的所有顶点的经纬度参数,提取该多边形范围内所有的user_id;

    这里需要两个基础函数

    一个是根据两个点的经纬度计算距离,calDistance;https://www.cnblogs.com/zhoug2020/p/3950933.html

    一个是判断一个点是否在给定的多边形内,isInPolygon;https://www.cnblogs.com/luxiaoxun/p/3722358.html

    方案一:SQL

    步骤

    1. 将calDistance和isInPolygon定义为UDF,一个sql即可得到结果;

    分析

    • 优点:简单;
    • 缺点:计算量大,运行缓慢,包含大量无用计算;

    方案一中会做大量的无用计算,而且calDistance和isInPolygon这两个高阶浮点计算非常昂贵

    1. 比如给定区域在河南省,但是其他省(比如河北)的用户数据也会参与计算,并且计算之后会被抛弃;
    2. 比如给定区域在河南省郑州市,但是其他市(比如洛阳)的数据也会参与计算,并且计算之后会被抛弃;
    3. 比如给定区域在河南省郑州市中原区,但是其他区(比如金水区)的数据也会参与计算并且计算之后会被抛弃;

    为了优化这些无用计算得到方案二如下:

    方案二

     步骤

    1. 根据给定区域(河南省郑州市中原区内)只查询必要的用户位置数据,比如只查询郑州市的用户数据(为什么不直接查中原区的数据?因为第一种情形虽然中心店在中原区,但是半径较大时可能区域包含其他区),读取数据量缩小到原来的1%以下,避免了无用计算中的1和2;
    2. 对给定区域(圆或者多边形)求一个能包含该区域同时边长最小的长方形,这样可以很容易的通过判断一个点是否长方形内来避免calDistance或isInPolygon计算,比如如果一个点在长方形外可以直接抛弃,将高阶浮点运算转化为简单的数字比较运算,计算数据量缩小到原来的万分之一以下,简化和避免了无用计算中的3;
    3. 对长方形范围内的所有用户数据计算calDistance或isInPolygon来获取精确结果;

    分析

    • 优点:改进了方案一中的大量无用计算,避免或者简化;
    • 缺点:依然包含部分无用计算,比如区域内的点也要计算一遍,并且无法快速响应一些需求,比如快速返回区域内的用户数量;

    方案二可以抽象为映射,第一轮映射是利用省市区信息来减少读取数据量,第二轮映射是利用是否在正方形外来减少计算数据量;并且这两轮映射都是现成的,或者很容易计算的;如果把映射改为网格grid,则效果比上述两轮映射更好,得到方案三如下:

    方案三

    步骤

    1. 预处理,将所有用户位置数据进行网格划分并标记存储,比如按每平方公里划分网格(同时得到网格的顶点经纬度),网格内存储该网格内所有的用户位置数据,同时存储一些统计信息,比如用户总量,不重复的用户总量,不重复的用户集合等,放到任意KV存储中;
    2. 根据给定区域计算哪些网格在区域内(区域内的网格不需要计算),哪些网格在区域边上(区域边上的网格需要计算,因为网格内部分用户在区域内,部分用户在区域外),这个是纯图形计算;
    3. 读取所有区域内的网格的不重复的用户集合数据(直接使用),读取所有区域边上的网格的所有用户位置数据(计算后使用),可以快速得到区域内用户数量或者用户列表;

    分析

    • 优点:相比方案二进一步减少读取数据量和计算数据量,并且可以满足一些快速响应的需求,可以通过减小网格的面积来进一步减少读取数据量和计算数据量,当网格的面积足够小以后,还可以在误差容许的范围内,将区域边上的网格‘认为’在区域内,避免所有的计算;
    • 缺点:需要预处理,并且需要额外的KV存储;

    另外还可以利用ElasticSearch对GIS的支持 https://www.elastic.co/blog/geo-location-and-search

  • 相关阅读:
    初学 Delphi 嵌入汇编[13] 地址参数用 [] 取值
    初学 Delphi 嵌入汇编[17] 逻辑运算
    初学 Delphi 嵌入汇编[11] 用汇编重写一个 Delphi 函数
    初学 Delphi 嵌入汇编[12] 在汇编代码中可以直接使用 Result
    初学 Delphi 嵌入汇编[19] Delphi 的无符号整数类型
    分享:tcpproxy实现
    Socket编程之简单介绍 蓝天下的雨 博客园
    分享:libuv 中文编程指南
    分享:《编程之美》求二叉树中节点的最大距离
    CentOS6.0下编译最新版本boost库
  • 原文地址:https://www.cnblogs.com/barneywill/p/9805703.html
Copyright © 2011-2022 走看看