我有一个包含数百万行数据的大型文本文件。第一列包含位置坐标。我需要从这个原始数据创建另一个文件,但是它只包含基于位置坐标的指定的非连续间隔。我有另一个文件,包含每个间隔的坐标。例如,我的原始文件格式与此类似:
Position Data1 Data2 Data3 Data4
55 a b c d
63 a b c d
68 a b c d
73 a b c d
75 a b c d
82 a b c d
86 a b c d
然后让我说我的文件包含看起来像这样的间隔......
name1 50 72
name2 78 93
然后我希望我的新文件看起来像这样...
Position Data1 Data2 Data3 Data4
55 a b c d
63 a b c d
68 a b c d
82 a b c d
86 a b c d
到目前为止,我已经创建了一个函数,用于将包含在特定时间间隔内的原始文件中的数据写入我的新文件。我的代码如下:
def get_block(beg,end):
output=open(output_table,'a')
with open(input_table,'r') as f:
for line in f:
line=line.strip("\r\n")
line=line.split("\t")
position=int(line[0])
if int(position)<=beg:
pass
elif int(position)>=end:
break
else:
for i in line:
output.write(("%s\t")%(i))
output.write("\n")
然后我创建一个包含我的间隔对的列表,然后使用上面的函数循环遍历我的原始文件:
#coords=[[start1,stop1],[start2,stop2],[start3,stop3]..etc]
for i in coords:
start_p=int(i[0]) ; stop_p=int(i[1])
get_block(start_p,stop_p)
这会执行我想要的操作,但是当它沿着我的坐标列表移动时它会以指数方式变慢,因为我必须通读整个文件,直到每次通过循环到达指定的开始坐标。有没有更有效的方法来实现这一目标?有没有办法每次跳过特定的行而不是读取每一行?
答案 0 :(得分:0)
感谢您使用pandas
的建议。以前,我原来的代码已经运行了大约18个小时,只完成了一半。使用pandas
,它在5分钟内创建了我想要的文件。为了将来参考,如果其他人有类似的任务,这里是我使用的代码。
import pandas as pd
data=pd.io.parsers.read_csv(input_table,delimiter="\t")
for i in coords:
start_p=int(i[0]);stop_p=int(i[1])
df=data[((data.POSITION>=start_p)&(data.POSITION<=stop_p))]
df.to_csv(output_table,index=False,sep="\t",header=False,cols=None,mode='a')
答案 1 :(得分:0)
我只是使用内置的csv
模块来简化读取输入。为了进一步加快速度,可以立即读入所有coord范围,这将允许选择过程一次性通过数据文件。
import csv
# read all coord ranges into memory
with open('ranges', 'rb') as ranges:
range_reader = csv.reader(ranges, delimiter='\t')
coords = [map(int, (start, stop)) for name,start,stop in range_reader]
# make one pass through input file and extract positions specified
with open('output_table', 'w') as outf, open('input_table', 'rb') as inf:
input_reader = csv.reader(inf, delimiter='\t')
outf.write('\t'.join(input_reader.next())+'\n') # copy header row
for row in input_reader:
for coord in coords:
if coord[0] <= int(row[0]) <= coord[1]:
outf.write('\t'.join(row)+'\n')
break;