提高 R 中字符串匹配的性能和速度

Tom*_*m A 1 string performance r

我有性能问题需要帮助。请耐心等待我的解释:

我有一个已知汽车 Vin# 和年份的数据库(为方便起见,仅显示前 4 行 ~5,000 行):

>vinDB
>ToyotaCarola 2008
 IJDINJNDJIJKNDJIMKDK0897
 NissanAltima 1998
 LJIODJJNJDJNJDNJNJDJ7765
Run Code Online (Sandbox Code Playgroud)

我还有一个 .txt 文档,其中通过以下方式显示了唯一的 DMV ID、车辆识别号和参考号(为方便起见,仅显示了 4 行约 5500 万行):

>carFile
>#DMVcorrNumber33:1245638:563892:6378
 IJDINJNDJIJKNDJIMKDK0897
 +
 VIN#IDref6388546
 #DMVcorrNumber33:1245638:563892:6378
 LJIODJJNJDJNJDNJNJDJ7765
 +
 VIN#IDref2453663
Run Code Online (Sandbox Code Playgroud)

我想要做的是扫描“vinDB”文件中的每隔一行(VIN#)与“carFile”文件中的每隔四行(从第二行开始)进行完美匹配。如果匹配存在,我想输出汽车的名称,以及它在“carFile”文件中出现的次数。

所以基本上,我需要这个:

    Car          Year     NumTimesFound
ToyotaCarola     2008          238
NissanAltima     1998          1755
Run Code Online (Sandbox Code Playgroud)

到目前为止,我有以下代码,它适用于截断的“carFile”文件,但当我尝试使用大约 5500 万行时,我的 R 程序崩溃了:

VinCounter<-function(carFile, vinDB)

{
i=1   #index inner while loop
j=1   #index outer while loop
m=2   #index of vinDB, starts at '2' because first VIN# is on line 2
s=2   #index of carFile
count=0

while(j<=length(rownames(vinDB))/2)  # VIN# is on every 2nd line in vinDB file
{
  while(i<=length(rownames(carFile))/4)# VIN# is on every 4th line in carFile file
  {
    if(vinDB[m,1]==carFile[s,1])
      {
      count=count+1
      s=s+4
      }
    else
      {
      s=s+4
      }
    i=i+1
  }
 print(vinDB[m-1,1])
 print(count)
 count=0
 s=2
 i=1
 m=m+2
 j=j+1
 }  

}
Run Code Online (Sandbox Code Playgroud)

所以,基本上,我想弄清楚如何:

1)使上面的代码更快、更高效。

2) 如何将我的输出存储在 .txt 或 .csv 文件中(因为现在,它只是在屏幕上显示输出)。

谢谢!

Bro*_*ieG 5

您可以使用以下命令相对轻松地完成此操作data.table:

vin.names <- vinDB[seq(1, nrow(vinDB), 2), ]
vin.vins <- vinDB[seq(2, nrow(vinDB), 2), ]
car.vins <- carFile[seq(2, nrow(carFile), 4), ]

library(data.table)
dt <- data.table(vin.names, vin.vins, key="vin.vins")
dt[J(car.vins), list(NumTimesFound=.N), by=vin.names]
#         vin.names NumTimesFound
#  1:     Ford 2014            15
#  2: Chrysler 1998            10
#  3:       GM 1998             9
#  4:     Ford 1998            11
#  5:   Toyota 2000            12
# ---                            
# 75:   Toyota 2007             7
# 76: Chrysler 1995             4
# 77:   Toyota 2010             5
# 78:   Toyota 2008             1
# 79:       GM 1997             5    
Run Code Online (Sandbox Code Playgroud)

要理解的主要事情是,J(car.vins)我们正在创建一个data.table与 vins 匹配的一列(J只是 的简写data.table,只要您在 a 中使用它data.table)。通过使用data.tableinside dt,我们将 的 列表加入vins到汽车列表中,因为我们dt在上一步中输入了“vin.vins”键。最后一个参数告诉我们将连接集分组,中间的参数我们想知道每个组的vin.names实例数量(是一个特殊变量)。.N.Ndata.table

另外,我还制作了一些垃圾数据来运行它。今后也请提供这样的数据。

set.seed(1)
makes <- c("Toyota", "Ford", "GM", "Chrysler")
years <- 1995:2014
cars <- paste(sample(makes, 500, rep=T), sample(years, 500, rep=T))
vins <- unlist(replicate(500, paste0(sample(LETTERS, 16), collapse="")))
vinDB <- data.frame(c(cars, vins)[order(rep(1:500, 2))])               
carFile <- 
  data.frame(
    c(rep("junk", 1000), sample(vins, 1000, rep=T), rep("junk", 2000))[order(rep(1:1000, 4))]
  )  
Run Code Online (Sandbox Code Playgroud)