R语言空间换时间算法、Hash键值对在字符串处理中的应用

最近一直在处理交通数据,有时间、车牌,经过的路口地址,数据量较大,本篇针对各车经过的路口时间先后顺序,生成贵阳交通的可通行有向图,即相连的交通路口间是否是双向通行、单向通行。

一、关于数据的说明

  • 车牌号,路口地址都是字符串
  • 时间是日期时间格式
  • 数据量大概有680万

二、原始算法代码

rm(list=ls(all=TRUE))
gc()
library(RODBC)

channel=odbcConnect("transport-connector-R", uid="transport", pwd="transport")  #连接mysql test 数据库
sqlTables(channel)  # 显示test数据库中的表格

#检索test.transport20140901 中贵阳的车辆信息,含车牌,经过的路口
transections_data<-sqlQuery(channel,"select plate,address from transport20140901 where plate like '贵A%' order by plate,time")
odbcClose(channel)

# 读取文件中排序好的路口地址数据
address_file <-file("/home/wanglinlin/transport/address.txt","r")
sorted_address <-readLines(address_file)
close(address_file)
#sorted_address[256]

#生成贵阳交通路口连通性有向图初始矩阵
transection_count <- length(sorted_address)
tansport_map <- matrix(0,transection_count,transection_count)
#tansport_map

#根据目标地址名称,在地址表中查找其位置编号
find_address<- function(target,address_table){
  len=length(address_table)
  for(i in 1:len)
    if(target==address_table[i])
      return (i)
  return (0)
}

#根据贵阳本地车辆信息,生成贵阳交通图的双向有向图矩阵
transport_data_count <- 6725490
counter <- transport_data_count-1
transection_id_one=find_address(transections_data[1,2],sorted_address)
for (i in 1:counter){
  transection_id_two=find_address(transections_data[i+1,2],sorted_address)
  if (transections_data[i,1]==transections_data[i+1,1]){
    tansport_map[transection_id_one,transection_id_two] <- 1
  }
  transection_id_one <- transection_id_two
}
write.table(tansport_map,"/home/wanglinlin/transport/tansport_map_two.txt",row.names = FALSE,col.names = FALSE)

上述代码核心为for循环中的语句,for的循环次数不可能减少了,循环中耗时的操作有两个:

<ul><li><span style="font-family: Arial, Helvetica, sans-serif;">find_address(transections_data[i+1,2],sorted_address)</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">transections_data[i,1]==transections_data[i+1,1]</span></li></ul>

这两个操作分别是在数组中查找字符串的位置(当前路口地址在地址列表中的位置),比较两个字符串是否相等(两个车牌号是否相同),都是关于字符串的操作,相当耗时。

事实上,find_address已经是优化过的操作了,之前最初是which函数,找到所有匹配的位置,返回第一个位置,每次查找都要遍历整个列表。

上图昨天下午3:00左右开始运行的程序,循环次数截止今天上午9:15仅运行了14412次,要运行完整个程序耗时要几十天时间,是不可接受的。

昨晚一直在改算法,希望不进行字符串操作即可以完成,最好的操作就是把车牌号,路口地址数字化,用数字对比,效率会大大提高。

这样,最好的解决方案就是用散列或者hash键值对操作,找了好半天,终于找到R的hash包可以进行这样的操作。用hash包把路口地址和车牌转换成键值对保存在内存中,把对路口地址位置的查找转换成hash值的查找,把车牌号的对比转换成车牌hash值的查找。

最后代码如下:

rm(list=ls(all=TRUE))
gc()
library(RODBC)
library(hash)

channel=odbcConnect("transport-connector-R", uid="transport", pwd="transport")  #连接mysql test 数据库
sqlTables(channel)  # 显示test数据库中的表格

#检索test.transport20140901 中贵阳的车辆信息,含车牌,经过的路口
transections_data<-sqlQuery(channel,"select plate,address from transport20140901 where plate like '贵A%' order by plate,time")
#找出贵阳所有车牌号,并散列化,形成键值对表
plates<-sqlQuery(channel,"select distinct plate from transport20140901 where plate like '贵A%'")
odbcClose(channel)
plate_list=(as.matrix(plates))[,1]
plate_count=length(plate_list)
plate_hash_pairs=hash(plate_list,1:plate_count)

# 读取文件中排序好的路口地址数据
address_file <-file("/home/wanglinlin/transport/address.txt","r")
sorted_address <-readLines(address_file)
sorted_address_hash_pairs<-hash(sorted_address,1:269)
close(address_file)
#sorted_address[256]

#生成贵阳交通路口连通性有向图初始矩阵
transection_count <- length(sorted_address)
transport_map <- matrix(0,transection_count,transection_count)
#tansport_map

#根据贵阳本地车辆信息,生成贵阳交通图的双向有向图矩阵
transport_data_count <- 6725490
counter <- transport_data_count-1
plate_hash_pairs[[as.character(transections_data[1,1])]]
plate_hash_pairs[[as.character(transections_data[2,1])]]
sorted_address_hash_pairs[[as.character(transections_data[1,2])]]
sorted_address_hash_pairs[[as.character(transections_data[2,2])]]
for (i in 1:counter){
  if (plate_hash_pairs[[as.character(transections_data[i,1])]]==plate_hash_pairs[[as.character(transections_data[i+1,1])]]){
    transport_map[sorted_address_hash_pairs[[as.character(transections_data[i,2])]],sorted_address_hash_pairs[[as.character(transections_data[i+1,2])]]] <- 1
  }
}
write.table(transport_map,"/home/wanglinlin/transport/transport_map.txt",row.names = FALSE,col.names = FALSE)

最终结果,今天早上8点半到电脑前,发现已经运行完了,结果数据就不再展示了。

总的算法效率提高了几百倍。

时间: 2024-11-02 16:49:51

R语言空间换时间算法、Hash键值对在字符串处理中的应用的相关文章

算法题:复制复杂链表之空间换时间法

说明:本文仅供学习交流,转载请标明出处,欢迎转载!  题目:复制一个复杂链表,所谓复杂链表指的是每个节点含有两个指针,一个指向单链表的下一个结点,一个指向单链表中的任意某个结点,或者该指针为空. 为了方便起见,我们将待复制的链表称为原型链表,将复制后的新链表称为复制链表,将指向下一个结点的指针定义为next指针,指向其他位置的指针定义为any指针.<剑指offer>上给出了三种解决方法:(1)常规法:(2)空间换时间法:(3)紧随复制法.书上并给出了第三种方法的实现代码.这里我根据书上的提示,

用空间换时间,内存数据库不止于快

近年来随着内存价格的下跌内存数据库正变得日益流行起来,内存数据库的性能也有了飞跃式的发展.然而很多开发人员在考虑内存数据库时只想到了速度,这无疑忽视了内存技术真正的潜力. 内存提供的不仅仅是更快的速度,它也是一种以存储空间换时间的方式.很多开发人员对于内存数据库的使用有一些疑虑,下面我们就来一一说明: 1.内存数据库运行比较快.除了快还有什么别的吗?我们知道内存的读写比硬盘快得多,所以将表全都加载到内存中就可以达到很高的读写速度.虚拟内存的大小受到交换分区的限制而通常交换分区的大小是内存的一到两

代码重构,空间换时间,dictionary 不要用object ,需明确指定类型

代码重构时,因为修改数据库成本很大,于是,可以在缓存中存储一份期待状态的数据结构: 例如,状态转换: 目标状态,中间件状态,原状态,三个状态之间转换时, 原来的逻辑是:目标状态<--中间件状态<--原状态,可以改为<原状态,中间件状态>-->目标状态, 一般情况下,服务器搭建在虚拟机上时,一般是存储位置大小不再考虑范围之内,cpu的计算能力是共享的,所以一个原则是::用"空间"换"时间",, 貌似: hashtable 和 dictio

求质数数量 - 空间换时间

质数:被自己本身和1整出的数 int getPrimeCount(int value){ int count = 0; int arr[301] = {0};// 0 - is prime , 1 - is not prime int num = (int)sqrt((float)value); for(int i = 2; i <= num ; ++i){ if (!arr[i]){ for(int j = i; i * j < value; ++j){ arr[i * j] = 1; }

递归小题中的空间换时间思想

题目: 如数: 1  1  2  3   5   8   13   21  34  55 ...... 序号: 0  1  2  3   4   5   6     7    8    9 ...... 由用户输入序号,输出对应的数值. 效果: 实现代码: #include <stdio.h> int bian(int num); //static int shu[100]={1,1}; int main() { int num; while ( printf("请输入编号数:&qu

Elasticsearch实战 | 必要的时候,还得空间换时间!

1.应用场景 实时数据流通过kafka后,根据业务需求,一部分直接借助kafka-connector入Elasticsearch不同的索引中. 另外一部分,则需要先做聚类.分类处理,将聚合出的分类结果存入ES集群的聚类索引中.如下图所示: 业务系统的分层结构可分为:接入层.数据处理层.数据存储层.接口层. 那么问题来了? 我们需要基于聚合(数据处理层)的结果实现检索和聚合分析操作,如何实现更快的检索和更高效的聚合分析效果呢? 2.方案选型 方案一: 只建立一个索引,aggs_index. 数据处

基于R语言的梯度推进算法介绍

通常来说,我们可以从两个方面来提高一个预测模型的准确性:完善特征工程(feature engineering)或是直接使用Boosting算法.通过大量数据科学竞赛的试炼,我们可以发现人们更钟爱于Boosting算法,这是因为和其他方法相比,它在产生类似的结果时往往更加节约时间. Boosting算法有很多种,比如梯度推进(Gradient Boosting).XGBoost.AdaBoost.Gentle Boost等等.每一种算法都有自己不同的理论基础,通过对它们进行运用,算法之间细微的差别

R语言空间分析功能简介

大家知道,R语言的软件包都是各领域专家贡献而来,通过一个统一的开放的语言环境神奇地组装到了一起,然后开始产生化学反应,为大数据分析立下汗马功劳. R中已经有一个Spatial软件包.通过library(sp)即可加载,如果提示没有安装,使用install.packages("sp")进行安装即可,安装过程中需要选择一个软件分发站的镜像. 然后使用getClass("Spatial")即可查看类的信息.返回信息如下: > getClass("Spati

R语言-缺少参数, 也没有缺省值

"缺少参数, 也没有缺省值"--在R语言自编函数中,如果参数没有输入值则会报这个错误. 1.问题 例如: > my.func my.func<-function(p){ print("TEST IS OK!") print(p) } > my.func() [1] "TEST IS OK!" Error in print(p) : 在为'print'函数选择方法时评估'x'参数出了错: 错误: 缺少参数"p"