R实现大文本文件数据分组汇总的方法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
R实现大文本文件数据分组汇总的方法
使用R语言对文件数据分组汇总是很普遍的操作,但有时我们会遇到比较大的文件,这类文件的计算结果较小,但源数据太大,无法全部放入内存进行计算,只能采用分批读取、分批计算、拼合结果的办法来解决。下面用一个例子来说明R实现大文件数据分组汇总的方法。
有个1G的文件sales.txt,存储着大量订单记录,我们要对CLIENT字段分组并对AMOUNT 字段汇总。该文件的列分割符为“\t”,前几行数据如下:
R语言解决方案
1con <- file("E: \\sales.txt", "r")
2result=read.table(con,nrows=100000,sep="\t",header=TRUE)
3result<-aggregate(result[,4],list(result[,2]),sum)
4while(nrow(databatch<-read.table(con,header=FALSE,nrows=100000,sep="\t",s=c(" ORDERID","Group.1","SELLERID","x","ORDERDATE")))!=0) {
5databatch<-databatch[,c(2,4)]
6result<-rbind(result,databatch)
7result<-aggregate(result[,2],list(result[,1]),sum)
8}
9close(con)
部分计算结果
代码解读:
1行:打开文件句柄。
2-3行:读入第一批的十万条数据,分组汇总后存入result。
4-8行:循环读数。每批次读入十万行数据,存入databatch变量。然后取第2和第4个字段,即“CLIENT”和“AMOUNT”。接着将databatch拼合到result中,再执行分组运算。
可以看到,同一时刻只有databatch和result会占用内存,其中databatch有十万条记录,
result是汇总结果,而汇总结果通常较小,不会超出内存。
11行:关闭文件句柄。
注意事项:
关于数据框。R语言的数据框不直接支持大文件,因此要用循环语句来辅助解决。具体的算法是:读一批数据,拼合到数据框result,对result分组汇总,再读下一批数据。可以看到,循环语句这部分的代码略显复杂。
关于列名。由于第一行数据是列名,因此第一批数据可以用header=TRUE直接设置列名,但后续数据没有列名,所以要用header=FALSE来读数。使用header=FALSE时,默认的列名是V1、V2…,而分组汇总后的默认列名是Group.1、x,因此还要用s来改名,这样才能使两者结构一致,方便后续的合并。列名这部分很容易出错,值得注意。
替代方案:
同样的算法也可以用Python、集算器、Perl等语言来实现。和R语言一样,这几种语言都可以实现大文本文件的分组汇总,以及后续的结构化数据计算。下面简单介绍集算器和Python的解决方案。
集算器会自动分批处理数据,程序员无需用循环语句手工控制,因此代码非常简洁:
cursor是集算器中用于结构化数据计算的数据类型,和数据框的用法差不多,但对大文件和复杂计算更擅长。另外,代码中的@t选项表示文件的第一行是列名,因此之后的计算可以直接用列名,这一点比较方便。
Python的代码结构和R差不多,也是手工控制循环,但python本身缺乏数据框或cursor 等结构化数据类型,因此代码更底层些:
1f rom itertools import groupby
2f rom operator import itemgetter
3r esult = []
4m yfile = open("E:\\sales.txt",'r')
5B UFSIZE = 10240000
6m yfile.readline()
7l ines = myfile.readlines(BUFSIZE)
8v alue=0
9w hile lines:
10for line in lines:
11record=line.split('\t')
12result.append([record[1],float(record[3])])
13result=sorted(result,key=lambda x:(x[0])) #分组前的排序
14batch=[]
15for key, items in groupby(result, itemgetter(0)): #使用groupby函数分组
16value=0
17for subItem in items:value+=subItem[1]
18batch.append([key,value]) #最后把汇总结果拼成二维数组
19result=batch
20lines = myfile.readlines(BUFSIZE)
21m yfile.close()
除了上述的二维数组,Python也可以用第三方包来实现,比如pandas就有类似数据框的结构化数据对象。pandas可以简化代码,和R的算法差不多,但pandas对大文件的支持同样有限,仍然需要编写循环完成。