我有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包中包含嵌入的数据库引擎.
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)
如果您更喜欢使用帖子中的方法,我认为通过在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.