簡體   English   中英

從文件python寫入特定行

[英]write specific lines from a file python

我有兩個文件,在其中一個文件中,我有一個基因座列表( Loci.txt )( Loci.txt約為1600萬個),在第二個文件中,我有一個行號列表( Pos.txt )。 我要做的是僅將Pos.txt文件中指定的Loci.txt中的行寫入新文件。 下面是兩個文件的截斷版本:

Loci.txt

R000001 1
R000001 2
R000001 3
R000001 4
R000001 5
R000001 6
R000001 7
R000001 8
R000001 9
R000001 10

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
R000001 3
R000001 5
R000001 9
R000001 10

問題是,當我將其應用於整個數據集時,我不得不從包含1600萬行的文件中提取大約1300萬行,這將永遠需要完成。 無論如何,我可以編寫這段代碼以使其運行得更快嗎?

您編寫代碼的速度很慢,主要是因為您在列表中搜索是否必須打印行: if i+1 in Lines 每次程序掃描完整列表以查找行號是否存在時。
您可以替換:

Lines = []

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

通過:

Lines = {}

for line in File1:
    Lines[int(line)] = True

您可以嘗試這樣的事情:

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]))

該解決方案的關鍵點是:

  1. 在第一步中創建枚舉(使用字典)
  2. 避免一次讀取整個File2(與語句一起使用)

另外,我使用File1和File2中包含的整數(代碼),因為我認為File1序列中可能有空洞。 否則,其他解決方案也是可能的。

正如其他人提到的那樣,首先導致讀取整個文件的內存是導致問題的原因。 這是另一種方法,它掃描大文件並只寫出匹配的那些行。

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_keys.txt文件非常大,轉換filtered_keysset將提高查找時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM