台北公共自行车预测

来源:互联网 发布:吸附平衡浓度算法 编辑:程序博客网 时间:2024/04/20 08:14

原文地址:http://supstat.com.cn/blog/2015/01/07/taipei-city-bike-prediction/


这篇文章是2014年10月21日~29日在台北参加“国际Open Data应用实务班”的学员的报告。

项目

演示程序运行在https://yaoch29.shinyapps.io/taipei-city-bike-prediction。源代码在https://github.com/hsu-yc/taipei-city-bike-prediction,文章中的文件路径都是相对于项目的根目录。

目标

项目的目标是提供一个台北市公共自行车站的概览[图1],用来预测给定自行车站任意时间的自行车可用量,并对一段时期内可用量的趋势做可视化的呈现[图2]。

图1

图2

数据抓取与预处理

我们是从公开网站http://taipei.youbike.com.tw/cht/f12.php采集数据,该页面包含台北市所有公共自行车站当前的自行车数量和空位的数量,数据每分钟更新一次。

由于网页上的数据表是用javascript动态生成的,所以在项目里我们用正则表达式来解析script标签中的内容,而不是去解析HTML的内容。下面的代码提取网页的源代码,并从脚本中提取出编码后的字符串,再从字符串中反解出JSON对象,最终将JSON对象转换成数据框,请看fetch-data.R。数据字段里包含经度和纬度[图3],以及可用自行车的精确位置。

library(RCurl)url <- 'http://taipei.youbike.com.tw/cht/f12.php'htmlSource = getURL(url, .encoding = 'utf-8')library(stringr)encodedJson = str_match(htmlSource, "*/\r\n\t\\w*='(.*)';\\w*=JSON.parse")[2]json = URLdecode(encodedJson)library(rjson)jsonData = fromJSON(json)newData <- data.frame(matrix(unlist(jsonData), nrow=length(jsonData), byrow=T))

图3

我们在服务器上设置了cron定时任务,每分钟抓取一次数据,请看脚本crontab.txt。该任务将每天的数据保存成单独的rdata文件。然后用combine-data.R合并每天的数据文件,在进一步分析之前用preprocess-data.R计算自行车的可用量。

时间序列模型

我们用时间序列模型预测工作日自行车的可用量。选择的数据来自11月3日至11月7日的工作日。[图4]显示的是用R的函数ts()stl()计算出的时间序列季节效应和趋势效应,请看脚本plot-time-series.R。时序图显示出自行车可用量每天的变化模式[图5]。

图4

图5

下面的代码是用R的forecast()函数为每个自行车站做提前24小时的预测,请看脚本predict.R。注意到,下面的预测把负值处理为0。到目前为止,用于web应用程序的数据已经准备好了。

library(forecast)library('plyr')source('preprocess-data.R')datePattern = '%Y%m%d'dataInWeekdays = data[data$time >= strptime('20141103', datePattern)      & data$time < strptime('20141108', datePattern),]ids = levels(data$id)ids = ids[ids != '0180']frequency = 60 * 24predictionByStationId = list()for(id in ids){  print(id)  #time series  xData = dataInWeekdays[dataInWeekdays$id == id,]  ind_size = length(xData$id)  five_day_ind = 1:ind_size  xData.ts = ts(xData$ratio, start=1, frequency=frequency)  fit = stl(xData.ts, 'periodic')  #prediction  pred = as.numeric(forecast(fit, h=frequency)$mean)  header = xData[1,]  predictionByStationId[[as.character(id)]] = list(    id=header$id,    name=header$name,    district=header$district,    address=header$address,    lat=header$lat,    lon=header$lon,    ratios=pred  )}save(predictionByStationId, file='predictionByStationId.rda')

Web应用

我们做出的web应用程序主要是以地图为用户界面的,用户可以查看所有自行车站的情况,也可以点到某一个自行车站查看详细信息[图6]。从绿到红的颜色梯度表示的是自行车可用性从高到低的变化范围。用户拖动时间滑动条可以查看感兴趣的时间点的情况。当用户点击地图上的标记,程序会弹出一个窗口显示对给定时间的预测概率。弹出的窗口同样可以显示未来5小时内的趋势[图2]。

图6

我们在这个项目中选择的应用程序框架是shiny,它可以直接访问之前用R处理的预测数据,并且大大提升了R的作图功能,请看server.R。我们的应用程序整合了Google地图的功能,并用HTML实现了定制化的UI,请看www/index.html。定制化的HTML UI拥有非常强的灵活性,可以使用JQuery和Bootstrap CSS来增强前端的功能。

本项目的演示程序部署在ShinyApps.io,shiny本身就有一键部署的功能。


0 0