从python文件中写入特定行

从python文件中写入特定行,python,Python,我有两个文件,其中一个是基因座列表(locis.txt)(确切地说是1600万),第二个文件是行号列表(Pos.txt)。我要做的是只将Pos.txt文件中指定的locis.txt中的行写入新文件。以下是两个文件的截断版本: loces.txt R000001 1 R0000012 R0000013 R0000014 R0000015 R0000016 R0000017 R0000018 R0000019 R00000110 Pos.txt 1 3. 5. 9 10 以下是我为该任务编写的代

我有两个文件,其中一个是基因座列表(
locis.txt
)(确切地说是1600万),第二个文件是行号列表(
Pos.txt
)。我要做的是只将
Pos.txt
文件中指定的
locis.txt
中的行写入新文件。以下是两个文件的截断版本:

loces.txt

R000001 1
R0000012
R0000013
R0000014
R0000015
R0000016
R0000017
R0000018
R0000019
R00000110
Pos.txt

1
3.
5.
9
10
以下是我为该任务编写的代码

#!/usr/bin/env python

import os
import sys

F1 = sys.argv[1]
F2 = sys.argv[2]
F3 = sys.argv[3]

File1 = open(F1).readlines()
File2 = open(F2).readlines()
File3 = open(F3, 'w')
Lines = []

for line in File1:
    Lines.append(int(line))

for i, line in enumerate(File2):
    if i+1 in Lines:
        File3.write(line)
代码的工作方式与我希望的完全相同,输出如下所示

OUT.txt

R000001 1
R0000013
R0000015
R0000019
R00000110

问题是,当我将其应用于我的整个数据集时,我必须从一个包含1600万行的文件中提取大约1300万行,这需要永远的时间才能完成。我是否可以编写此代码以使其运行更快

您可以尝试以下方法:

import sys

F1 = sys.argv[1]
F2 = sys.argv[2]
F3 = sys.argv[3]

File1 = open(F1)
File2 = open(F2)
File3 = open(F3, 'w')

for linenumber in File2:
    for line in File1:
        if linenumber in line:
            File3.write(line)
            break

由于嵌套的for循环,这看起来可能很糟糕,但由于我们正在迭代文件的行,因此脚本将从发现最后一行时停止的位置继续。这是因为读取文件是如何工作的,指针用于跟踪您在文件中的位置。为了再次从文件的开头读取,您必须使用seek函数将指针移动到文件的开头。

您可以尝试使用以下代码:

#!/usr/bin/env python

with open("loci.txt") as File1:
    lociDic = {int(line.split()[1]): line.split()[0] for line in File1}

with open("pos.txt") as File2:
    with open("result.txt", 'w') as File3:
        for line in File2:
            if int(line) in lociDic:
                File3.write(' '.join([lociDic[int(line)], line]))
此解决方案的关键点是:

  • 在第一步中创建枚举(使用字典)
  • 避免一次读取整个文件2(使用with语句)

  • 我还使用File1和File2中包含的整数(代码),因为我假设File1序列中可能存在漏洞。否则,其他解决方案也是可能的。

    您编写代码的速度很慢,主要是因为您正在列表中搜索必须打印的行:
    如果行中的i+1
    。每次程序扫描完整列表时,都会查找行号是否在中。
    您可以替换:

    Lines = []
    
    for line in File1:
        Lines.append(int(line))
    
    作者:


    正如其他人提到的,首先读取内存中的整个文件是导致问题的原因。这里是另一种方法,它扫描大文件并只写出匹配的行

    with open('search_keys.txt', 'r') as f:
        filtered_keys = [line.rstrip() for line in f]
    
    with open('large_file.txt', 'r') as haystack, open('output.txt', 'w') as results:
        for line in haystack:
            if len(line.strip()):  #  This to skip blanks
                if line.split()[1] in filtered_keys:
                    results.write('{}\n'.format(line))
    
    这样,您一次只读取一行大文件,同时写出结果

    请记住,这不会对输出进行排序


    如果您的
    search\u keys.txt
    文件非常大,将
    filtered\u keys
    转换为
    set
    将缩短查找时间。

    好吧。。。您不必首先一次性读取整个
    文件2
    ,以节省内存。另外,您可能应该使用内存缓冲区来编写,而不是执行
    .write()
    在找到的每一行。我有一件事要说,pos文件的实时长度是多少。我的pos文件的实时长度是13398648。代码运行得非常快,但由于某种原因,我只得到589行,而不是13398648@iksaglam:文件中的某些行可能与您公开的模式不匹配。对不起,这段代码不输出pos.txt中的数字,当数字在pos.txt中时,它会输出在空格后包含数字的行。@NicolasDefranoux:准确,我是如何在底部写的。我不认为pos.txt包含要保留的行的locis.txt编号,而是一个必须与pos.txt中包含的代码匹配的代码。仅此而已。代码速度很快,但当我将其应用于真实数据时,我只得到589行,而不是13398648行。是否可能是轨迹或Pos文件的行号不符合顺序?
    with open('search_keys.txt', 'r') as f:
        filtered_keys = [line.rstrip() for line in f]
    
    with open('large_file.txt', 'r') as haystack, open('output.txt', 'w') as results:
        for line in haystack:
            if len(line.strip()):  #  This to skip blanks
                if line.split()[1] in filtered_keys:
                    results.write('{}\n'.format(line))