R实现大文本文件数据分组汇总的方法

使用R语言对文件数据分组汇总是很普遍的操作,但有时我们会遇到比较大的文件,这类文件的计算结果较小,但源数据太大,无法全部放入内存进行计算,只能采用分批读取、分批计算、拼合结果的办法来解决。下面用一个例子来说明R实现大文件数据分组汇总的方法。

有个1G的文件sales.txt,存储着大量订单记录,我们要对CLIENT字段分组并对AMOUNT字段汇总。该文件的列分割符为“\t”,前几行数据如下:


R语言解决方案

    con <- file("E: \\sales.txt", "r")

result=read.table(con,nrows=100000,sep="\t",header=TRUE)

result<-aggregate(result[,4],list(result[,2]),sum)

while(nrow(databatch<-read.table(con,header=FALSE,nrows=100000,sep="\t",col.names=c("

ORDERID","Group.1","SELLERID","x","ORDERDATE")))!=0) {

databatch<-databatch[,c(2,4)]

result<-rbind(result,databatch)

result<-aggregate(result[,2],list(result[,1]),sum)

}

close(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,因此还要用col.names来改名,这样才能使两者结构一致,方便后续的合并。列名这部分很容易出错,值得注意。

 

替代方案:

同样的算法也可以用Python、集算器、Perl等语言来实现。和R语言一样,这几种语言都可以实现大文本文件的分组汇总,以及后续的结构化数据计算。下面简单介绍集算器和Python的解决方案。

集算器会自动分批处理数据,程序员无需用循环语句手工控制,因此代码非常简洁:

cursor是集算器中用于结构化数据计算的数据类型,和数据框的用法差不多,但对大文件和复杂计算更擅长。另外,代码中的@t选项表示文件的第一行是列名,因此之后的计算可以直接用列名,这一点比较方便。

Python的代码结构和R差不多,也是手工控制循环,但python本身缺乏数据框或cursor等结构化数据类型,因此代码更底层些:

from itertools import groupby

from operator import itemgetter

result = []

myfile = open("E:\\sales.txt",‘r‘)

BUFSIZE = 10240000

myfile.readline()

lines = myfile.readlines(BUFSIZE)

value=0

while lines:

for line in lines:

record=line.split(‘\t‘)

result.append([record[1],float(record[3])])

result=sorted(result,key=lambda x:(x[0])) #分组前的排序

batch=[]

for key, items in groupby(result, itemgetter(0)): #使用groupby函数分组

value=0

for subItem in items:value+=subItem[1]

batch.append([key,value]) #最后把汇总结果拼成二维数组

result=batch

lines = myfile.readlines(BUFSIZE)

myfile.close()

除了上述的二维数组,Python也可以用第三方包来实现,比如pandas就有类似数据框的结构化数据对象。pandas可以简化代码,和R的算法差不多,但pandas对大文件的支持同样有限,仍然需要编写循环完成。

时间: 2024-11-18 07:13:26

R实现大文本文件数据分组汇总的方法的相关文章

R实现大文本文件数据过滤的方法

使用R语言过滤文件数据是很普遍的操作,但有时我们会遇到比较大的文件,这类文件无法全部读入内存处理,需要采用分批读取.分批过滤.拼合结果的办法来解决.下面用一个例子来说明R实现大文件数据过滤的方法. 有个1G的文件sales.txt,存储着大量订单记录,请过滤出AMOUNT字段值在2000和3000之间的记录.该文件的列分割符为"\t",前几行数据如下:     R语言解决方案: con <- file("E:\\sales.txt", "r"

R语言实现固定分组汇总的方法

组名称和组数量已知的分组汇总被称为固定分组汇总,此类算法的分组依据来自于数据集之外,比如:按照参数列表中的客户名单分组,或按照条件列表进行分组.此类算法会涉及分组依据是否超出数据集.是否需要多余的组.数据是否重叠等问题,解决起来有一定的难度.本文将介绍R语言实现固定分组汇总的方法.  例1:分组依据不超出数据集 数据框sales是订单记录,其中CLIENT列是客户名,AMOUNT列是订单金额,请将sales按照"潜力客户列表"进行分组,并对各组的AMOUNT列汇总求和.潜力客户列表为[

Java实现文本文件分组汇总的简便方法

程序开发中经常会碰到处理文本文件中数据的情况,这里通过一个例子来看用java实现文本文件分组汇总的方法:从文本文件employee.txt中读取员工信息,按照DEPT分组,求出每组的员工个数COUNT和薪酬SALARY总额. 文本文件empolyee.txt的格式如下: EID   NAME       SURNAME        GENDER  STATE        BIRTHDAY        HIREDATE         DEPT         SALARY 1      

R运行大数据的过程中遇到的问题:不能有负长度矢量

解决办法: 只能通过一些trick来减小生成的中间矩阵的大小.比如我所遇到的问题是: 我要运行(W%*%H%*%t(H)) 这句话,(W的规模是5000000*10,而H的规模是10*100000) 解释执行W%*%H的时候报错:不能有负长度矢量. 坑爹的中文报错,google发现,和中文有关的R文档.记录真是少得可怜,终于通过英文“negative length vectors are not allowed”这句话, 看到老外们的解释,才知道了,简而言之就是因为数据规模太大,而R系统不允许生

集算器协助Java处理结构化文本之分组汇总

直接用Java实现文体文件分组汇总会有如下的麻烦: 1.文件不是数据库,不能用SQL访问.当分组.汇总表达式变化时,只能改写代码.而要实现灵活表达式的话,需要自己实现动态表达式解析和求值,编程工作量非常大. 2.遍历过程中记录分组结果,结果小了还可以存在内存中,如果分组结果太大时要将中间结果缓存进临时文件再归并,实现过程非常复杂. 使用集算器辅助Java编程,这些问题都有现成的类库可以解决.下面,我们通过例子来看一下具体作法. 文本文件employee.txt中保存有员工信息,我们要按照DEPT

集算器并行处理大文本文件的示例

集算器可以方便地用并行方式处理大文本文件,下面通过一个例子来说明使用方法. 假设有个一千万条销售记录的文本文件sales.txt,其主要字段是SellerID(销售员).OrderDate(订单日期).Amount(订单金额),请计算每个销售员在近四年里的大订单总金额.其中,金额在2000以上的属于大订单. 要进行并行处理,首先要能对文件进行分段,集算器提供了游标数据对象cursor及其函数,可以方便地分段读取大文本文件.比如file("e:/sales.txt")[email pro

Java读写大文本文件(2GB以上)

如下的程序,将一个行数为fileLines的文本文件平均分为splitNum个小文本文件,其中换行符'r'是linux上的,windows的java换行符是'\r\n': package kddcup2012.task2.FileSystem; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import 

MySQL 大数据量快速插入方法和语句优化

MySQL大数据量快速插入方法和语句优化是本文我们主要要介绍的内容,接下来我们就来一一介绍,希望能够让您有所收获! INSERT语句的速度 插入一个记录需要的时间由下列因素组成,其中的数字表示大约比例: 连接:(3) 发送查询给服务器:(2) 分析查询:(2) 插入记录:(1x记录大小) 插入索引:(1x索引) 关闭:(1) 这不考虑打开表的初始开销,每个并发运行的查询打开. 表的大小以logN (B树)的速度减慢索引的插入. 加快插入的一些方法 如果同时从同一个客户端插入很多行,使用含多个VA

[译]用R语言做挖掘数据《七》

时间序列与数据挖掘 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到: 1. LX终端(LXTerminal): Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令2. GVim:非常好用的编辑器,最简单的用法可以参考课程Vim编辑器3. R:在命令行输入‘R’进入交互式环境,下面的代码都是在交互式环境运行4. 数据:在命令行终端输入以下命令: