通过文件处理缩短长度

Roc*_*ket 9 python python-2.7

我有2个代码执行与我要求的相同的工作,但我仍然没有为我的数据集获得任何有用或更好的代码以使其对我有用,首先让我清楚我在做什么.我有2 TEXT文件,一个名字input_num和第二个名字,input_data因为它有明确的名称,其中input_num.txt有数字,并input_data有数据,这2个文件是8至10 MB,让我告诉你他们的一些部分,这是'input_num.txt'

ASA5.txt DF4E6.txt DFS6Q7.txt
Run Code Online (Sandbox Code Playgroud)

还有这个 input_data.txt

>56|61|83|92|ASA5
Dogsarebarking
Run Code Online (Sandbox Code Playgroud)

这2个是他们的文本文件的某些部分,input_data.txt必须包含最后一栏ASA5等等,这些都是数据input_num.txt,所以程序先检查最后一列>56|61|83|92|ASA5ASA5不是转到input_num.txt5,它含有一定的价值input_num.txt就像4在上面,所以它回到input_data.txtgoto的话,把它们切成4,

我有2个代码:1个

import os
import re
file_c = open('num_data.txt')
file_c = file_c.read()
lines = re.findall(r'\w+\.txt \d+', file_c)
numbers = {}

for line in lines:
    line_split = line.split('.txt ')
    hash_name = line_split[0]
    count = line_split[1]
    numbers[hash_name] = count
file_i = open('input_data.txt')
file_i = file_i.read()

for hash_name, count in numbers.iteritems():
    regex = '(' + hash_name.strip() + ')'
    result = re.findall(r'>.*\|(' + regex + ')(.*?)>', file_i, re.S)

    if len(result) > 0:
        data_original = result[0][2]
        stripped_data = result[0][2][int(count):]
        file_i = file_i.replace(data_original, '\n' + stripped_data)
f = open('input_new.txt', 'wt')
f.write(file_i)
f.close()
Run Code Online (Sandbox Code Playgroud)

而第二个是

import csv
output = open('output.txt' , 'wb')
def get_min(num):
    return int(open('%s.txt' % num, 'r+').readlines()[0])
last_line = ''
input_list = []

#iterate over input.txt in sort the input in a list of tuples 
for i, line in enumerate(open('input.txt', 'r+').readlines()): 
    if i%2 == 0: 
        last_line = line
    else:
        input_list.append((last_line, line))
filtered = [(header, data[:get_min(header[-2])] + '\n' ) for (header, data) in input_list]
[output.write(''.join(data)) for data in filtered]
output.close()
Run Code Online (Sandbox Code Playgroud)

Lev*_*sky 5

至于我从第一个代码的问题描述中可以理解,你想要N输出中的第一个字母,而实际上你得到除了第一个N字母之外的所有字母.这可以通过改变来解决

stripped_data = result[0][2][int(count):]
Run Code Online (Sandbox Code Playgroud)

stripped_data = result[0][2][:int(count)]
Run Code Online (Sandbox Code Playgroud)

我还认为使用的正则表达式并不完全准确.我建议以下数字:

with open('num.txt') as nums:
    lines = re.findall(r'\w+\.txt\s+\d+', nums.read())

numbers = {}
for line in lines:
    line_split = re.split(r'\.txt\s+', line)
    count = line_split[1]
    numbers[line_split[0]] = int(line_split[1])
Run Code Online (Sandbox Code Playgroud)

和以下数据:

with open('input_data.txt') as file_i:
     data = file_i.read()

for name, count in numbers.iteritems():
    result = re.search(r'\|{}\n(.*?)(>|$)'.format(name), s, re.S)
    if result:
        data_original = result.group(1)
        stripped_data = data_original[:count]
        data = data.replace(data_original, stripped_data)
with open('input_new.txt', 'w') as f:
    f.write(data)
Run Code Online (Sandbox Code Playgroud)

但请注意,这个想法仍然存在缺陷,因为您在进行操作时可能会意外更改多个序列replace.此方法也是内存效率低的,因为文件作为一个字符串被读入内存.我建议对数据使用迭代解析器,就像我下面提到的那样.


无论如何,如果我必须解决这个问题,我会用来pyteomics读写FASTA文件(因为我写了它并且总是把它放在手边).

格式input_num.txt很糟糕,所以我认为你的第一个例子中的代码是提取信息的最佳代码.我做了一些修复:

import re
from pyteomics import fasta

with open('num.txt') as nums:
    lines = re.findall(r'\w+\.txt\s+\d+', nums.read())

numbers = {}
for line in lines:
    line_split = re.split(r'\.txt\s+', line)
    count = line_split[1]
    numbers[line_split[0]] = int(line_split[1])

with fasta.read('data.txt') as data:
    new_data = ((header, seq[:numbers.get(header.rsplit('|', 1)[-1])])
            for header, seq in data)
    fasta.write(new_data, 'new_data.txt')
Run Code Online (Sandbox Code Playgroud)

另一方面,由于您的数据看起来更像DNA序列,而pyteomics用于蛋白质组学,因此使用它可能更有意义BioPython.SeqIO:

import re
from Bio import SeqIO

with open('num.txt') as nums:
    lines = re.findall(r'\w+\.txt\s+\d+', nums.read())

numbers = {}
for line in lines:
    line_split = re.split(r'\.txt\s+', line)
    count = line_split[1]
    numbers[line_split[0]] = int(line_split[1])
data = SeqIO.parse(open('data.txt'), 'fasta')

def new_records():
    for record in data:
        record.seq = record.seq[:numbers.get(record.description.rsplit('|', 1)[-1])]
        yield record

with open('new_data.txt', 'w') as new_data:
    SeqIO.write(new_records(), new_data, 'fasta')
Run Code Online (Sandbox Code Playgroud)