大文件的切割与归并(数据分析案例三)

  • 本节内容的数据见电脑F:\python数据\Python海量数据(精缩版)百度网盘“我的数据文件/Python海量数据”

本节内容基于大文件里面内容的快速查找的基础上延申

1.先了解以下QQ.txt
在这里插入图片描述

2.读取数据的行数

filepath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/QQfile/QQ.txt"
QQfile=open(filepath,"rb")
i=0
while True:
    line=QQfile.readline()
    if i%10000000==0: #读取的时候,每100万读取一次
        print(i)
    if not line:
        break
    else:
        i+=1
print("end=",i)
QQfile.close()

在这里插入图片描述

3.将倒排索引存到文件里

def getuser(num):
    csdninputfile.seek(num,0)  #跳到文件的位置。根据文件排序
    line=csdninputfile.readline()
    line=line.decode("gbk","ignore")
    linelist=line.split("----")
    if len(linelist)==2:
        return linelist[0]
    else:
        return ""

filepath="QQ.txt"
csdninputfile=open(filepath,"rb")
csdnlist=csdninputfile.readlines()

lengthlist=[0]
for  line in csdnlist:
    lengthlist.append(len(line)) #读取每一行的长度到数组
del  csdnlist
print("read")

i=0
length=len(lengthlist)
while i <length -1:
    lengthlist[i]+=lengthlist[i-1] #叠加,确定每一行的文件位置
    i+=1
del lengthlist[len(lengthlist)-1] #删除最后一个
print("get")
lengthlist.sort(key=lambda x:getuser(x))#根据文件排序索引,
print("sort")

print("index made")
indexfilepath="QQindex.txt"
saveindexfile=open(indexfilepath,"wb")
for  i  in range(len(lengthlist)-1):
    #保存为等长,为了随机访问
    saveindexfile.write(format(lengthlist[i],"15d").encode("utf-8"))
saveindexfile.close()

在这里插入图片描述
事实上,这个程序要运行四五十分钟而且会中途崩掉好几次(数据量巨大)




因为数据量实在是太巨大了,所以我们必须对大文件进行切割和归并处理




一、数据切割算法

1.把num平均分成N等分

  • 我们想把100个数切分成10个文件,那么切割得到[10,10,10,10,10,10,10,10,10,10]
  • 而如果这个数不是整数,如97,那我们想把它切割成10个文件,可以切分成[10,10,10,10,10,10,10,10,10,7]
    具体的算法是[10,10,10,10,10,10,10,10,10,7]里面包含[(97-97%10)//(10-1)]个10和1个7
  • 103想切分成10个文件,那么就是[11,11,11,11,11,11,11,11,11,4],里面包含[(103-103%10)//(10-1)]个11和1个4
  • num想切分成N个文件,每个文件包含[(num-num%N)//(N-1)]个数以及一个额外的数
def  evgSplit(num,N):
    lastlist=[]
    if  num%N==0:
        for  i  in range(N):
            lastlist.append(num//N)
    else:
        evg= (num-num%N)//(N-1)
        for i  in range(N-1):
            lastlist.append(evg)
            num=num-evg  
        lastlist.append(num)
    return lastlist


print( evgSplit(100,10))
print( evgSplit(97,10))
print( evgSplit(103,10))
print( evgSplit(84319637,10))

在这里插入图片描述

2.把大文件均分成N个小文件

def  evgSplit(num,N):
    lastlist=[]
    if  num%N==0:
        for  i  in range(N):
            lastlist.append(num//N)
    else:
        evg= (num-num%N)//(N-1)
        for i  in range(N-1):
            lastlist.append(evg)
            num-=evg
        lastlist.append(num)
    return lastlist

filelineslist=evgSplit(84319637,10) #84319637是QQ.txt的行数,filelineslist得到一个[9368847, 9368847, 9368847, 9368847, 9368847, 9368847, 9368847, 9368847, 9368847, 14]的列表
filepath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/QQfile/QQ.txt"
filedir="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/QQfile/qqsplit"
allfile=open(filepath,"rb")
for  i  in range(len(filelineslist)):
    tmpfilepath=filedir+"/QQ"+str(i)+".txt"  #如:E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/QQfile/qqsplit//QQ0.txt"
    tmpfile=open(tmpfilepath,"wb")
    for  j in range(filelineslist[i]):
        line=allfile.readline()
        tmpfile.write(line)
    tmpfile.close()
allfile.close()

在这里插入图片描述

二、数据归并算法

import  os
filedir="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/QQfile/qqsplit"  #原来的那10个文件都在这个目录下
#print(os.listdir(filedir))  得到['QQ0.txt','QQ1.txt','QQ2.txt','QQ3.txt'...]
allfilepath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/QQfile/QQMerge.txt"  #这是合并的文件
allfile=open(allfilepath,"wb")
for  filename in  os.listdir(filedir):
    print(filedir+"//"+filename)  #如:"E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/QQfile/qqsplit//QQ0.txt"
    tmpfile=open(filedir+"//"+filename,"rb")
    while True:
        line=tmpfile.readline()
        if not line:
            break
        else:
            allfile.write(line)
    tmpfile.close()
allfile.close()

在这里插入图片描述

三、数据归并排序法

1.头索引排序
我们不能对一个大文件一次性排序那就只能先对切割后的小文件分别排序然后归并
在这里插入图片描述


def merge(mylist1,mylist2):
    listall=[]
    while  len(mylist1)>0 and len(mylist2)>0:
        if mylist1[0] <mylist2[0]:
            listall.append(mylist1[0])
            del  mylist1[0]
        elif mylist1[0]>mylist2[0]:
            listall.append(mylist2[0])
            del mylist2[0]
        else:  #两个数相等的时候
            listall.append(mylist1[0])
            del mylist1[0]
            listall.append(mylist2[0])
            del mylist2[0]
    listall.extend(mylist2)  #假如列表1已经空了,那就直接把列表2里的元素添加进listall里去
    listall.extend(mylist1)  #假如列表2已经空了,那就直接把列表1里的元素添加进listall里去
    return listall


mylist1=[5,7,6,7,8,1,3]
mylist2=[2,4,2,6,10,8]
mylist1.sort()
mylist2.sort()
print(merge(mylist1,mylist2))

在这里插入图片描述

2.下标排序
之前排序时会边合并边删去小文件里的元素,如果小文件不能删的时候,那就得用下表排序


def merge(mylist1,mylist2):
    listall=[]
    i=0
    j=0
    while  i<len(mylist1) and j <len(mylist2):
        if mylist1[i]<mylist2[j]:
            listall.append(mylist1[i])
            i+=1
        elif mylist1[i]>mylist2[j]:
            listall.append(mylist2[j])
            j += 1
        else:
            listall.append(mylist1[i])
            i += 1
            listall.append(mylist2[j])
            j += 1
    while i <len(mylist1):  #当mylist2已经遍历完而mylist1还没有遍历完的时候
        listall.append(mylist1[i])
        i+=1
    while j <len(mylist2):
        listall.append(mylist2[j])
        j+=1


    return listall

mylist1=[5,7,6,7,8,1,3]
mylist2=[2,4,2,6,10,8]
mylist1.sort()
mylist2.sort()
print(merge(mylist1,mylist2))

在这里插入图片描述

四、对人人网的数据文件进行归并排序

1.直接对人人网数据排序

renrenpath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/xh-2.txt"
renrenfile=open(renrenpath,"rb")
renrenlist=renrenfile.readlines()
renrenfile.close()
print("read")
renrenlist.sort(key=lambda x:x.decode("gbk","ignore")) #别忘了解码,要不然你看不了
print("sort")


renrensortpath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/xhsort-2.txt"
renrensortfile=open(renrensortpath,"wb")
for  line in renrenlist:
    renrensortfile.write(line)
renrensortfile.close()
print("save")

2.将人人网数据切割

#已知该文件有4768600行,我们把它切割成两个文件,一个是2000000行,一个是2768600

filelineslist=[2000000,2768600]
filepath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/xh-2.txt"
filedir="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/"
allfile=open(filepath,"rb")
for  i  in range(len(filelineslist)):
    tmpfilepath=filedir+"/renren____"+str(i)+".txt"
    tmpfile=open(tmpfilepath,"wb")
    for  j in range(filelineslist[i]):
        line=allfile.readline()
        tmpfile.write(line)
    tmpfile.close()
allfile.close()

在这里插入图片描述
3.将切割后两个数据文件进行内部排序

renrenpath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/renren____0.txt"
renrenfile=open(renrenpath,"rb")
renrenlist=renrenfile.readlines()
renrenfile.close()
print("read")
renrenlist.sort(key=lambda x:x.decode("gbk","ignore")) #别忘了解码,要不然你看不了
print("sort")


renrensortpath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/renren____0sort.txt"
renrensortfile=open(renrensortpath,"wb")
for  line in renrenlist:
    renrensortfile.write(line)
renrensortfile.close()
print("save")


renrenpath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/renren____1.txt"
renrenfile=open(renrenpath,"rb")
renrenlist=renrenfile.readlines()
renrenfile.close()
print("read")
renrenlist.sort(key=lambda x:x.decode("gbk","ignore")) #别忘了解码,要不然你看不了
print("sort")


renrensortpath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/renren____1sort.txt"
renrensortfile=open(renrensortpath,"wb")
for  line in renrenlist:
    renrensortfile.write(line)
renrensortfile.close()
print("save")

在这里插入图片描述
4.将切割后的两个文件进行归并排序

#renren____0sort.txt 有:2000000行
#renren____0sort.txt 有:2768600行


path1="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/renren____0sort.txt"
path2="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/renren____1sort.txt"
mergepath="E:/python数据分析/百度网盘/Python数据分析海量数据营销day4/Python数据分析海量数据营销day4/renren500w_16610/renren_Merge_sort.txt"
file1=open(path1,"rb")
file2=open(path2,"rb")
filelast=open(mergepath,"wb")
file1length=2000000
file2length=2768600

i=0
j=0
str1=file1.readline() #读一行
str2=file2.readline() #读一行
linestr1=str1.decode("gbk","ignore")
linestr2=str2.decode("gbk","ignore")
while i<file1length and  j<file2length:
    if linestr1<linestr2:
        filelast.write(str1)
        str1=file1.readline()
        linestr1=str1.decode("gbk","ignore")
        i+=1

    elif linestr1>linestr2:
        filelast.write(str2)
        str2 = file2.readline()
        linestr2 = str2.decode("gbk", "ignore")
        j+=1

    else:  #(当linestr1=linestr2时,把两个都写进去)
        filelast.write(str1)
        str1 = file1.readline()
        linestr1 = str1.decode("gbk", "ignore")
        i += 1
        filelast.write(str2)
        str2 = file2.readline()
        linestr2 = str2.decode("gbk", "ignore")
        j += 1
#当有一个文件已经遍历完的时候(i=file1length or  j=file2length)时就执行下面这个程序
while i <file1length: #(当file2已经遍历完而file1还没有遍历完)
    filelast.write(str1)
    str1=file1.readline()
    i+=1


while j <file2length:
    filelast.write(str2)
    str2=file2.readline()
    j+=1


file1.close()
file2.close()
filelast.close()

在这里插入图片描述

四、对QQ数据文件进行归并排序

在这里插入图片描述
之前归并的是两个文件,如果要是有10个文件,你怎么归并效率最高呢?

1.如何做到两两归并
我们要把列表里的第一个数还有第二个数合并放到最后一位

def getlast(mylist):
    if len(mylist)<2: #长度小于二说明已经只剩下1个数了
        print(mylist)
        return mylist
    else:
        mylist.append(mylist[0]+mylist[1])
        del mylist[0]  #删除第一个
        del mylist[0]  #删除原来的第二个,删除原来的第一个后原来的第二个就成了现在的第一个文件了
        print(mylist)
        getlast(mylist)

mylist=['1','2','3','4','5','6','7','8','9','0']
getlast(mylist)

在这里插入图片描述
2.批量两两合并

def getlastX(mylist):
    if len(mylist)<2: #长度小于二说明已经只剩下1个数据了
        print(mylist)
        return mylist
    else:
        n=len(mylist)//2  #计算出我们要合并几对,10个那就合并5对,5个那就合并2对,3个合并1对
        for i in range(n): #将第0个和第1个合并,将第2个和第3个合并,将第4个和第5个合并
            mylist.append(mylist[2*i]+mylist[2*i+1])
        for  i in range(n):
            del mylist[0] #删除第一个
            del mylist[0] #删除原来的第二个,删除原来的第一个后原来的第二个就成了现在的第一个文件了
        print(mylist)
        getlastX(mylist)
mylist=['1','2','3','4','5','6','7','8','9','0']
getlastX(mylist)

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你的甲乙丙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值