http://training.data-artisans.com/是Apache Flink商业公司DataArtisans提供的一个flink学习平台,主要提供了一些业务场景和flink api结合的case。本文摘取其中一个计算出租车上/下客人热点区域demo进行分析。

一 数据准备

flink-traing的大部分例子是以New York City Taxi & Limousine Commission 提供的一份历史数据集作为练习数据源,其中最常用一种类型为taxi ride的事件定义为

rideId         : Long      // a unique id for each ride
taxiId : Long // a unique id for each taxi
driverId : Long // a unique id for each driver
isStart : Boolean // TRUE for ride start events, FALSE for ride end events
startTime : DateTime // the start time of a ride
endTime : DateTime // the end time of a ride,
// "1970-01-01 00:00:00" for start events
startLon : Float // the longitude of the ride start location
startLat : Float // the latitude of the ride start location
endLon : Float // the longitude of the ride end location
endLat : Float // the latitude of the ride end location
passengerCnt : Short // number of passengers on the ride

下载数据集

wget http://training.data-artisans.com/trainingData/nycTaxiRides.gz

将数据源转化为flink stream source数据

// get an ExecutionEnvironment
StreamExecutionEnvironment env =
StreamExecutionEnvironment.getExecutionEnvironment();
// configure event-time processing
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime); // get the taxi ride data stream
DataStream<TaxiRide> rides = env.addSource(
new TaxiRideSource("/path/to/nycTaxiRides.gz", maxDelay, servingSpeed));

二 坐标分格

如下图所示,程序将整个城市坐标由西北向东南划分为大约250X400个单位的单元格

三 根据单元格计算坐标值

基础坐标数据

    // geo boundaries of the area of NYC
public static double LON_EAST = -73.7;
public static double LON_WEST = -74.05;
public static double LAT_NORTH = 41.0;
public static double LAT_SOUTH = 40.5; // area width and height
public static double LON_WIDTH = 74.05 - 73.7;
public static double LAT_HEIGHT = 41.0 - 40.5; // delta step to create artificial grid overlay of NYC
public static double DELTA_LON = 0.0014;
public static double DELTA_LAT = 0.00125; // ( |LON_WEST| - |LON_EAST| ) / DELTA_LON
public static int NUMBER_OF_GRID_X = 250;
// ( LAT_NORTH - LAT_SOUTH ) / DELTA_LAT
public static int NUMBER_OF_GRID_Y = 400;

根据经纬度计算单元格唯一id

    public static int mapToGridCell(float lon, float lat) {
int xIndex = (int)Math.floor((Math.abs(LON_WEST) - Math.abs(lon)) / DELTA_LON);
int yIndex = (int)Math.floor((LAT_NORTH - lat) / DELTA_LAT); return xIndex + (yIndex * NUMBER_OF_GRID_X);
}

四 程序实现

将坐标映射到gridId之后剩下的就是采用窗口统计单位时间内event事件超过一定阈值的grid。

// find popular places
DataStream<Tuple5<Float, Float, Long, Boolean, Integer>> popularSpots = rides
// remove all rides which are not within NYC
.filter(new RideCleansing.NYCFilter())
// match ride to grid cell and event type (start or end)
.map(new GridCellMatcher())
// partition by cell id and event type
.<KeyedStream<Tuple2<Integer, Boolean>, Tuple2<Integer, Boolean>>>keyBy(0, 1)
// build sliding window
.timeWindow(Time.minutes(15), Time.minutes(5))
// count ride events in window
.apply(new RideCounter())
// filter by popularity threshold
.filter((Tuple4<Integer, Long, Boolean, Integer> count) -> (count.f3 >= popThreshold))
// map grid cell to coordinates
.map(new GridToCoordinates()); // print result on stdout
popularSpots.print();

上述flink job在统计完热点区域后又将gridId映射回每个单元格的中心点经纬度,具体实现为:

    /**
* Maps the grid cell id back to longitude and latitude coordinates.
*/
public static class GridToCoordinates implements
MapFunction<Tuple4<Integer, Long, Boolean, Integer>, Tuple5<Float, Float, Long, Boolean, Integer>> { @Override
public Tuple5<Float, Float, Long, Boolean, Integer> map(
Tuple4<Integer, Long, Boolean, Integer> cellCount) throws Exception { return new Tuple5<>(
GeoUtils.getGridCellCenterLon(cellCount.f0),
GeoUtils.getGridCellCenterLat(cellCount.f0),
cellCount.f1,
cellCount.f2,
cellCount.f3);
}
} /**
* Returns the longitude of the center of a grid cell.
*
* @param gridCellId The grid cell.
*
* @return The longitude value of the cell's center.
*/
public static float getGridCellCenterLon(int gridCellId) { int xIndex = gridCellId % NUMBER_OF_GRID_X; return (float)(Math.abs(LON_WEST) - (xIndex * DELTA_LON) - (DELTA_LON / 2)) * -1.0f;
} /**
* Returns the latitude of the center of a grid cell.
*
* @param gridCellId The grid cell.
*
* @return The latitude value of the cell's center.
*/
public static float getGridCellCenterLat(int gridCellId) { int xIndex = gridCellId % NUMBER_OF_GRID_X;
int yIndex = (gridCellId - xIndex) / NUMBER_OF_GRID_X; return (float)(LAT_NORTH - (yIndex * DELTA_LAT) - (DELTA_LAT / 2)); }

结论: 综上所示,通过单元格划分,flink程序可以方便的解决实时统计热点地理区域这一类问题。

代码地址:https://github.com/dataArtisans/flink-training-exercises/blob/master/src/main/java/com/dataartisans/flinktraining/exercises/datastream_java/windows/PopularPlaces.java

【flink training】 打车热点区域实时统计PopularPlaces的更多相关文章

  1. 通过Flink实现个推海量消息数据的实时统计

    背景 消息报表主要用于统计消息任务的下发情况.比如,单条推送消息下发APP用户总量有多少,成功推送到手机的数量有多少,又有多少APP用户点击了弹窗通知并打开APP等.通过消息报表,我们可以很直观地看到 ...

  2. 利用flash精确定位asp.net的图像热点区域

    Asp.net的热点区域控件非常有用,但是对于热点区域如何精确定位,设定矩形,圆和多边形要素点的位置,用flash能够精确定位,在flash中制作热点区域的部分,可以是矩形,图形或者文字,然后对于这部 ...

  3. PHP+Mysql+jQuery实现地图区域数据统计-展示数据

    我们要在地图上有限的区块内展示更多的信息,更好的办法是通过地图交互来实现.本文将给大家讲解通过鼠标滑动到地图指定省份区域,在弹出的提示框中显示对应省份的数据信息.适用于数据统计和地图区块展示等场景. ...

  4. jQuery - 实时统计输入框输入个数(中文输入法适用)

    经常在实时统计文本框输入多少字的时候,有时会出现不及时统计,特别是在中文输入法下. 为了实时准确统计,可以修改代码如下:     $(function() {        $("#txtT ...

  5. JavaScript 实现textarea限制输入字数, 输入框字数实时统计更新,输入框实时字数计算移动端bug解决

    textarea称文本域,又称文本区,即有滚动条的多行文本输入控件,在网页的提交表单中经常用到.与单行文本框text控件不同,它不能通过maxlength属性来限制字数,为此必须寻求其他方法来加以限制 ...

  6. DSAPI 获取实时统计信息CPU/内存/硬盘/网络

    有时,我们需要获取当前计算机中CPU.内存.硬盘.网络等实时信息,如下图:\ 要实现上述几项信息的获取,通常需要使用Timer控件来间隔获取,以便刷新最新的数据. 本示例中,放一个Timer控件,放一 ...

  7. Kafka项目实战-用户日志上报实时统计之编码实践

    1.概述 本课程的视频教程地址:<Kafka实战项目之编码实践>  该课程我以用户实时上报日志案例为基础,带着大家去完成各个KPI的编码工作,实现生产模块.消费模块,数据持久化,以及应用调 ...

  8. Kafka项目实战-用户日志上报实时统计之分析与设计

    1.概述 本课程的视频教程地址:<Kafka实战项目之分析与设计>  本课程我通过一个用户实时上报日志案例作为基础,带着大家去分析Kafka这样一个项目的各个环节,从而对项目的整体设计做比 ...

  9. Kafka项目实战-用户日志上报实时统计之应用概述

    1.概述 本课程的视频教程地址:<Kafka实战项目之应用概述> 本课程是通过一个用户实时上报日志来展开的,通过介绍 Kafka 的业务和应用场景,并带着大家搭建本 Kafka 项目的实战 ...

随机推荐

  1. JS 的一些基础算法题

    1.翻转字符串   例子(要求:先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序,最后把数组转化成字符串) function reverseString(str) { str=str. ...

  2. mysql将字符串字段转为数字排序或比大小

    SELECT * FROM Student WHERE 1 = 1 ORDER BY -ID DESC ; SELECT * FROM Student WHERE 1 = 1 ORDER BY (ID ...

  3. 使用Apache POI导出Excel小结--导出XLS格式文档

    使用Apache POI导出Excel小结 关于使用Apache POI导出Excel我大概会分三篇文章去写 使用Apache POI导出Excel小结--导出XLS格式文档 使用Apache POI ...

  4. python修改和获取进程名字:setproctitle

    参考: https://pypi.org/project/setproctitle/

  5. [转]Sql server 大数据量分页存储过程效率测试附代码

    本文转自:http://www.cnblogs.com/lli0077/archive/2008/09/03/1282862.html 在项目中,我们经常遇到或用到分页,那么在大数据量(百万级以上)下 ...

  6. tomcat下配置https环境(windows环境)

    在网上搜了一下,内容不是很完善.现进行整理,做个学习笔记,以备以后使用. (1)进入到jdk下的bin目录 (2)输入如下指令“keytool -v -genkey -alias tomcat -ke ...

  7. HDU4667(有错)

    正规的做法是找切点.三角形三个顶点分别对圆作切线,然后求切点(2个).两圆之间也要求切点(4个). 扯淡了这就..麻烦的要命.. 下面是写了一半的代码.. void process_circle(po ...

  8. Less is better than never

    很多时候,在正确的做一件事之前,我们总会尝试一些笨办法或者白费一些力气: 很多时候,即使在正确的做一件事,由于这事情并非一日之功,而没有收到立竿见影的效果: 之后,我们的内心便容易动摇,怀疑,甚至想要 ...

  9. java中,重构、重载、重写

    1.什么叫重构? 答:重构(Refactoring)就是通过调整程序代码改善软件的质量.性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性,系统发展到一定阶段后,使用重构的方式,不改变系 ...

  10. 关于天津中软国际ETC培训中心的见与闻

    半个月的时间转眼即逝,在中软国际天津ETC的实训的两个星期就这样过去了,在中软国际天津站的这段时间也收获了非常多.明确了非常多,了解了很多关于社会就业的知识以及关于软件培训的一些事情.尽管我的了解可能 ...