2013-04-12 32 views
9

Tôi có 2 mã đã thực hiện công việc tương tự như tôi đang yêu cầu, nhưng tôi vẫn không nhận được bất kỳ mã nào hữu ích hoặc tốt hơn cho tập dữ liệu của mình để làm cho nó hữu ích cho tôi. những gì tôi đang làm. Tôi có 2 TEXT tệp, một tên là input_num và tên thứ hai là input_data vì nó rõ ràng từ tên input_num.txt có số trong đó và input_data có dữ liệu trong đó, 2 tệp này là 8 đến 10 mb, hãy để tôi chỉ cho bạn một số của phần mình, Đây là 'input_num.txt'Độ dài cắt thông qua việc xử lý tập tin

ASA5.txt DF4E6.txt DFS6Q7.txt 

và điều này input_data.txt

>56|61|83|92|ASA5 
Dogsarebarking 

Những 2 là một số bộ phận của tập tin văn bản của họ, input_data.txt có cột cuối cùng có chứa ASA5 và vân vân , đây là dữ liệu từ input_num.txt, do đó, trước tiên chương trình kiểm tra cột cuối cùng của >56|61|83|92|ASA5ASA5 so với goto input_num.txt5, nó chứa một số giá trị trong input_num.txt như 4 ở trên, vì vậy nó quay trở lại input_data.txt cắt chúng đến 4,

tôi có 2 mã cho nó: 1 là

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

và thứ 2 là

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() 
+4

Câu hỏi/vấn đề của bạn ở đây là gì? Bạn nói rằng bạn có hai chương trình làm việc, và "Cả hai chương trình làm việc tốt hơn nhưng không chính xác cho tôi, có nghĩa là để nói không phải trên dữ liệu khổng lồ". Vậy ... họ làm gì sai? Sản lượng mong đợi so với đầu ra được quan sát là gì? Bạn có thể xác định những gì về đầu ra gây ra một vấn đề? (Và lý tưởng cho chúng tôi một đầu vào mẫu bị tước bỏ để tái tạo nó; nếu không, bạn có thể đăng các tệp 10MB ở đâu đó trong trường hợp ai đó muốn gỡ lỗi mã của bạn không?) – abarnert

+1

Ngoài ra, trong khi bạn nói bạn đã chọn sử dụng 'csv' bởi vì bạn cảm thấy thoải mái với nó ... bạn không thực sự sử dụng 'csv' cả. Bạn làm 'import' nó trong một trường hợp, nhưng bạn không bao giờ chạm vào nó. Bạn sử dụng một regex trong một chương trình, và dường như sử dụng các dòng hoàn chỉnh mà không cần cố gắng chia thành các cột trong cột kia. – abarnert

+3

Cuối cùng, nếu vấn đề bạn gặp phải với các tệp lớn là "nó quá chậm" hoặc "nó chiếm quá nhiều bộ nhớ", tôi cho tỷ lệ 1: 1 là vấn đề của bạn là 'readlines()' . Hầu như không bao giờ có lý do để sử dụng 'readlines()'. Nếu bạn chỉ làm 'cho i, dòng liệt kê (f)', nó cho bạn một dòng tại một thời điểm, đệm hiệu quả nhất có thể; nếu bạn làm 'cho i, dòng liệt kê (f.readlines())', trước tiên nó đọc và phân tích toàn bộ tệp trong bộ nhớ, và chỉ sau đó mới cung cấp cho bạn một dòng tại một thời điểm. Điều này không bao giờ hữu ích và thường là một vấn đề. – abarnert

Trả lời

5

Theo như tôi có thể hiểu từ mô tả của vấn đề của bạn với mã đầu tiên, bạn muốn các chữ cái đầu tiên N trong đầu ra trong khi trên thực tế bạn nhận được tất cả mọi thứ ngoại trừ các chữ cái đầu tiên N. Điều này có lẽ có thể được cố định bằng cách thay đổi

stripped_data = result[0][2][int(count):] 

để

stripped_data = result[0][2][:int(count)] 

Tôi cũng nghĩ rằng biểu thức thông thường được sử dụng là không hoàn toàn chính xác. Tôi đề nghị sau đây cho những con số:

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

và sau cho dữ liệu:

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) 

Nhưng lưu ý rằng ý tưởng là vẫn còn thiếu sót vì bạn vô tình có thể thay đổi nhiều hơn một chuỗi khi thực hiện replace. Ngoài ra phương pháp này là bộ nhớ không hiệu quả bởi vì các tập tin được đọc vào bộ nhớ là một chuỗi. Tôi đề nghị sử dụng một trình phân tích cú pháp lặp lại cho dữ liệu, giống như những gì tôi đề cập dưới đây.


Dù sao, nếu tôi đã phải giải quyết vấn đề này, tôi muốn sử dụng pyteomics để đọc và ghi các file FASTA (vì tôi đã viết nó và luôn luôn có nó tiện dụng).

Định dạng input_num.txt thật khủng khiếp, vì vậy tôi nghĩ mã từ ví dụ đầu tiên của bạn là ví dụ tốt nhất có thể làm để trích xuất thông tin.Tôi thực hiện một số bản sửa lỗi cho nó mặc dù:

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

Mặt khác, kể từ khi dữ liệu của bạn trông giống như chuỗi DNA và pyteomics là dành cho proteomics, nó có thể có ý nghĩa hơn để sử dụng 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') 
+0

Khi tôi tải về exe của 'pyteomics' cho python 2.7, nó cài đặt, và khi tôi import nó từ shell nó import mà không có lỗi, nhưng khi tôi import nó vào script nó cho tôi thấy lỗi không có tên fasta – Rocket

+0

@Angel Does' từ pyteomics nhập khẩu fasta' làm việc trong vỏ? (Ngoài ra tôi chỉ mở rộng câu trả lời trong phần về mã của bạn) –

+0

Có, nó nhập khẩu trong shell – Rocket

Các vấn đề liên quan