sql – R中大文件的操作

前端之家收集整理的这篇文章主要介绍了sql – R中大文件的操作前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有15个数据文件,每个大约4.5GB.每个文件是大约17,000个客户的数月数据.总之,这些数据代表了15个月内17,000名客户的信息.我想重新格式化这些数据,而不是每个表示一个月的15个文件,每个客户及其所有数据都有17,000个文件.我写了一个脚本来做到这一点:
#the variable 'files' is a vector of locations of the 15 month files
exists = NULL  #This vector keeps track of customers who have a file created for them
for (w in 1:15){  #for each of the 15 month files
  month = fread(files[w],select = c(2,3,6,16))  #read in the data I want
  custlist = unique(month$CustomerID) #a list of all customers in this month file
  for (i in 1:length(custlist)){ #for each customer in this month file
    curcust = custlist[i] #the current customer
    newchunk = subset(month,CustomerID == curcust) #all the data for this customer
    filename = sprintf("cust%s",curcust) #what the filename is for this customer will be,or is
    if ((curcust %in% exists) == TRUE){ #check if a file has been created for this customer. If a file has been created,open it,add to it,and read it back
      custfile = fread(strwrap(sprintf("C:/custFiles/%s.csv",filename)))#read in file
      custfile$V1 = NULL #remove an extra column the fread adds
      custfile= rbind(custfile,newchunk)#combine read in data with our new data
      write.csv(custfile,file = strwrap(sprintf("C:/custFiles/%s.csv",filename)))
    } else { #if it has not been created,write newchunk to a csv
      write.csv(newchunk,filename)))
      exists = rbind(exists,curcust,deparse.level = 0) #add customer to list of existing files
    }
  }
 }

该脚本有效(至少,我很确定).问题是它非常慢.按照我要的速度,它需要一周或更长时间才能完成,我没有那个时间.你们中的任何一个人在R中做得更好,更快捷吗?我应该尝试在像sql这样的事情吗?我以前从未真正使用过sql;你们中的任何人都可以告诉我这样的事情会怎样吗?非常感谢任何输入.

解决方法

作为@Dominic Comtois,我也建议使用sql.
R可以处理相当大的数据 – 有20亿行的好基准比python好 – 但是因为R主要在内存中运行,所以你需要有一台好的机器来使它工作.您的情况仍然不需要一次加载超过4.5GB的文件,所以它应该在个人计算机上可行,请参见快速数据库解决方案的第二种方法.
您可以使用R将数据加载到sql数据库,稍后从数据库查询它们.
如果您不了解sql,可能需要使用一些简单的数据库. R的最简单方法是使用Rsqlite(不幸的是,从v1.1开始它不再是精简版).您无需安装或管理任何外部依赖项. Rsqlite包中包含嵌入的数据库引擎.
library(Rsqlite)
library(data.table)
conn <- dbConnect(dbDriver("sqlite"),dbname="mydbfile.db")
monthfiles <- c("month1","month2") # ...
# write data
for(monthfile in monthfiles){
  dbWriteTable(conn,"mytablename",fread(monthfile),append=TRUE)
  cat("data for",monthfile,"loaded to db\n")
}
# query data
df <- dbGetQuery(conn,"select * from mytablename where customerid = 1")
# when working with bigger sets of data I would recommend to do below
setDT(df)
dbDisconnect(conn)

就这样.您使用sql而不必通常与数据库相关的开销很大.

如果您更喜欢使用帖子中的方法,我认为通过在data.table中进行聚合时按组执行write.csv可以大大加快速度.

library(data.table)
monthfiles <- c("month1","month2") # ...
# write data
for(monthfile in monthfiles){
  fread(monthfile)[,write.csv(.SD,file=paste0(CustomerID,".csv"),append=TRUE),by=CustomerID]
  cat("data for","written to csv\n")
}

因此,您可以在data.table中使用快速唯一,并在分组时执行子集,这也是超快的.以下是该方法的工作示例.

library(data.table)
data.table(a=1:4,b=5:6)[,file=paste0(b,".csv")),b]

更新2016-12-05:
从data.table 1.9.8开始,您可以用fwrite替换write.csv,例如this answer.

猜你在找的MsSQL相关文章