簡體   English   中英

在python中基於多個因素進行過濾

[英]filtering based on more than one factor in python

我有一個包含3列的文本文件,並希望基於第3列進行過濾。 第一列具有ID,第三列具有字符序列。 在第一列中,每個id重復,但在第三列中,每個重復序列的長度不同。 在某些情況下,由於沒有序列,因此將其替換為"not present" 我只想對每個id重復一個序列,並且該序列必須是最長的序列。

例:

RPL17   ENST00000584364 not present
RPL17   ENST00000579248 CTGCGTTGCTCCGAGGGCCCAATCCTCCTGCCATCGCCGCCATCCTGGCTTCGGGGGCGCCGGCCT
RPL17   ENST00000580210 GCCCGTGTGGCTACTTCTGTGGAAGCAGTGCTGTAGTTACTGGAAGATAAAAGGGAAAGCAAGCCCTTGGTGGGGGAAA
RPL18   ENST00000551749 not present
RPL18   ENST00000546623 not present
RPL18   ENST00000552588 TCTCTCTTTCCGGACCTGGCCGAGCAGGAGGCGCCATC
RPL18   ENST00000547897 ACCTGGCCGAGCAGGAGGCGCCATC
RPL18   ENST00000550645 GCCGAGCAGGAGGCGCCATC
RPL18   ENST00000552705 not present

結果:

RPL17   ENST00000580210 GCCCGTGTGGCTACTTCTGTGGAAGCAGTGCTGTAGTTACTGGAAGATAAAAGGGAAAGCAAGCCCTTGGTGGGGGAAA
RPL18   ENST00000552588 TCTCTCTTTCCGGACCTGGCCGAGCAGGAGGCGCCATC

我寫了這段代碼,中間部分做了幾次修改,但並沒有達到我想要的效果。

with open("file.txt") as f, open('test.txt', 'w') as outfile:
    for line in f:
        line=line.split(",")
           .
           .
           .
           outfile.writerow(entry)

看起來輸入文件是列格式。 因此,首先我們必須弄清楚哪些字段位於哪些列中,然后可以使用dict來確保對於給定的ID僅保留最長的序列。

這是我想您要的內容:

# 00000000001111111111222222222233333333334
# 01234567890123456789012345678901234567890
# RPL17   ENST00000584364 not present
from collections import OrderedDict
sequences = OrderedDict()
with open("file.txt") as f, open('test.txt', 'w') as outfile:
    for line in f:
        st_id = line[:8].strip()
        sequence = line[24:].strip()
        value, _ = sequences.get(st_id, ('', None))
        if not value or value == 'not present' or len(sequence) > len(value):
            sequences[st_id] = (sequence, line)
    for _, line in sequences.values():
        outfile.write(line)
from collections import defaultdict

d = defaultdict(list)
with open('you_data.txt') as f, open('out.txt', 'w') as out:
    s_line = [line.split('   ')for line in f]
    for k, v in s_line:
        d[k].append(v)
# {'RPL18': ['ENST00000551749 not present\n', 'ENST00000546623 not present\n', 'ENST00000552588 TCTCTCTTTCCGGACCTGGCCGAGCAGGAGGCGCCATC\n', 'ENST00000547897 ACCTGGCCGAGCAGGAGGCGCCATC\n', 'ENST00000550645 GCCGAGCAGGAGGCGCCATC\n', 'ENST00000552705 not present']
    for k, v in d.items():
        long_v = sorted(v, key=len, reverse=True)[0]
        out.write('   '.join([k, long_v]))

出:

RPL18   ENST00000552588 TCTCTCTTTCCGGACCTGGCCGAGCAGGAGGCGCCATC
RPL17   ENST00000580210 GCCCGTGTGGCTACTTCTGTGGAAGCAGTGCTGTAGTTACTGGAAGATAAAAGGGAAAGCAAGCCCTTGGTGGGGGAAA

在此處輸入圖片說明

我很確定這是您想要的,盡管我敢肯定可以將其清理掉。 maxitemgetter結合將返回具有最長序列的行的元組,並且由於這樣做是針對每個id的,因此它應該正是您想要的,並且可能是最快的排序方法。

我用逗號作為分隔符,因為您說過數據是用逗號分隔的,盡管您顯示給我們的內容是用空格分隔的,但是您可以將其更改為任何分隔符。 我用逗號分隔的輸出也可以,但是您也可以將其更改為您應該使用的輸出分隔符。

更新:上一行最后一行實際上並沒有正確設置行,並且在寫入行后我沒有將lines重置為空,因此它無法正常工作。 另外,由於我會重復編寫代碼,因此將make_row您需求的重要行放入函數( make_row )中。

我已經用逗號分隔數據進行了測試,並且效果很好。

from operator import itemgetter
import csv


def make_row(lines):
    return map(str.strip, max(lines, key=itemgetter(2)))

with open("file.txt") as f, open('test.txt', 'w') as outfile:
    output = csv.writer(outfile)
    id = ''
    lines = []
    for line in f:
        current_line = line.split(",")
        if current_line[0] != id and lines != []:
            output.writerow(make_row(lines))
            lines=[]
        id = current_line[0]
        if current_line[2].strip() != 'not present':
            lines.append(current_line)
    output.writerow(make_row(lines))  # to catch the last row

暫無
暫無

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

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