- 本节内容的数据见电脑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)