簡體   English   中英

比較大型清單中的項目-查找長度相差1個字母的項目-Python

[英]Comparing items in large list - finding items differing in 1 letter by length - Python

我正在尋找解決我一直困在Python中的問題。 我有一個文件,只有一欄,其中包含大約。 6,000行。 對於每一行,每個項目都是唯一的(已過濾此文件以刪除40,000行文件中的重復項)。 每行中的項目的長度各不相同,其中某些項目的長度與其他項目的長度相等。

單行示例:

IGHV3-30/33rn-IGHJ4-CARDPSLSSMITFGGVIVTRGYFDYW

或更多帶有制表符的示例,其中制表符在第三個“-”之后(不同的第一部分)分開:

IGHV3-23-IGHJ4  CAKDRGYTGYGVYFDYW
IGHV4-39-IGHJ4  CARHDILTGYSYYFDYW
IGHV3-23-IGHJ3  CAKSGGWYLSDAFDIW
IGHV4-39-IGHJ4  CARTGFGELGFDYW
IGHV1-2-IGHJ2   CARDSDYDWYFDLW
IGHV1-8-IGHJ3   CARGQTYYDILTGPSDAFDIW
IGHV4-39-IGHJ5  CARSTGDWFDPW
IGHV3-9-IGHJ3   CANVPIYSSSYDAFDIW
IGHV3-23-IGHJ4  CAKDWELYYFDYW
IGHV3-23-IGHJ4  CAKDRGYTGFGVYFDYW
IGHV4-39-IGHJ4  CARHLGYNNSWYPFDYW
IGHV1-2-IGHJ4   CAREGYNWNDEGRFDYW
IGHV3-23-IGHJ3  CAKSSGWYLSDAFDIW
IGHV4-39-IGHJ4  CARYLGYNSNWYPFDYW
IGHV3-23-IGHJ6  CAKEGCSSGCPYYYYGMDVW
IGHV3-23-IGHJ3  CAKWGPDAFDIW
IGHV3-11-IGHJ   CATSGGSP
IGHV3-11-IGHJ4  CARDGDGYNDYW
IGHV1-2-IGHJ4   CARRIGYSSGSEDYW
IGHV1-2-IGHJ4   CARDIAVPGHGDYW
IGHV6-1-IGHJ4   CASGGAVPGYYFDYW

在第一列中,有一些不同的項目。 在第二列中,每個項目都是唯一的。 第一列項目需要匹配,然后第二列項目需要以最小不匹配2進行排序。理想情況下,這可以與Levenshtein模塊一起使用,因為我可以放入最大值,但是我需要兩個字符串。 有沒有一種方法可以在一個列表中的每個項目上使用Levenshtein?

我需要做的是打開此文件(我認為先按長度排序可能會有所幫助,但是我不確定)。 在將所有項目按長度分組之后,我需要將這些項目分類為相差1個字符的組(第三個“-”之前的字符串必須相同,其中“-”之后的字符串僅應相差1個字符) 。)

我認為我遇到的問題是關於生成適當的for循環以遍歷項目長度的問題。

到目前為止,我擁有的代碼:

import sys
import os
import Levenshtein

inp = sys.argv[1] # Input file containing single column of items

with open(inp, "r") as f1:
        vj = [line.strip() for line in f1]

lengths = []
for k in vj:
        i = len(k)
        lengths.append(i)

lengths_sort = sorted(lengths, reverse = True)

uniq_len = []
for i in lengths_sort:
       if i not in uniq_len:
                uniq_len.append(i)

print uniq_len #For QC purposes

def get_new_list(strings, counts, outlist=[]):
        for s in strings:
                if len(s) == counts[0]:
                        outlist.append(s)
        return outlist

new_vj = get_new_list(vj, uniq_len, outlist=[])
print new_vj
ham = Levenshtein.hamming(new_vj[0], new_vj[1])
print ham

所以我一直在尋找的輸出是好的,但是還沒有完成:

[46, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18]
46
['IGHV3-30/33rn-IGHJ4-CAKDPSLSSMITFGGVIVTRGYFDYW', 'IGHV3-30/33rn-IGHJ4-CARDPSLSSMITFGGVIVTRGYFDYW']
1

有兩個長度為46的項目(巧合的是,第三個“-”之前的字符串是相同的;很好),它們在兩個字符串之間僅相差一個字符。

我的麻煩是,1.如何遍歷uniq_len列表中的數字作為“字符串”列表中匹配長度的輸入(請參見代碼中的函數)。 2.我想為每個不同的長度創建一個新列表。 3.如果每個新列表中都有多個項目,則所有項目的差異僅相差1個字符。

注意:“-”是使用UNIX paste -d-命令創建的,具有3個文件(每個文件包含1列)來創建此文件。 將這些文件與\\ t一起作為分隔符創建3列會更容易嗎?

因此,打開文件,刪除行,然后可以將第一列,第二列匹配,看看第三列是否相差一個或多個字符?

感謝所有幫助。

更新:修改為處理可變數量的“ id”子字段,並將結果打印為單個字符串。 請注意,在輸入的末尾添加了幾個測試用例,以使其中一些具有不同數量的前導字段構成id(即2而不是3)。

我還重命名了num_mismatches()函數hamming_distance()因為它就是這樣。

使用以下輸入:

IGHV3-23-IGHJ4-CAKDRGYTGYGVYFDYW
IGHV4-39-IGHJ4-CARHDILTGYSYYFDYW
IGHV3-23-IGHJ3-CAKSGGWYLSDAFDIW
IGHV4-39-IGHJ4-CARTGFGELGFDYW
IGHV1-2-IGHJ2-CARDSDYDWYFDLW
IGHV1-8-IGHJ3-CARGQTYYDILTGPSDAFDIW
IGHV4-39-IGHJ5-CARSTGDWFDPW
IGHV3-9-IGHJ3-CANVPIYSSSYDAFDIW
IGHV3-23-IGHJ4-CAKDWELYYFDYW
IGHV3-23-IGHJ4-CAKDRGYTGFGVYFDYW
IGHV4-39-IGHJ4-CARHLGYNNSWYPFDYW
IGHV1-2-IGHJ4-CAREGYNWNDEGRFDYW
IGHV3-23-IGHJ3-CAKSSGWYLSDAFDIW
IGHV4-39-IGHJ4-CARYLGYNSNWYPFDYW
IGHV3-23-IGHJ6-CAKEGCSSGCPYYYYGMDVW
IGHV3-23-IGHJ3-CAKWGPDAFDIW
IGHV3-11-IGHJ-CATSGGSP
IGHV3-11-IGHJ4-CARDGDGYNDYW
IGHV1-2-IGHJ4-CARRIGYSSGSEDYW
IGHV1-2-IGHJ4-CARDIAVPGHGDYW
IGHV6-1-IGHJ4-CASGGAVPGYYFDYW
IGHV1-2-CAREGYNWNDEGRFDYW
IGHV4-39-CARSTGDWFDPW
IGHV1-2-CARDSDYDWYFDLW

和這個腳本:

from collections import defaultdict
from itertools import izip, tee
import os
import sys

# http://en.wikipedia.org/wiki/Hamming_distance#Algorithm_example
def hamming_distance(s1, s2):
    """ Count number of mismatched characters in equal length strings. """
    if not isinstance(s1, basestring): raise ValueError('s1 is not a string')
    if not isinstance(s2, basestring): raise ValueError('s2 is not a string')
    if len(s1) != len(s2): raise ValueError('string lengths do not match')
    return sum(a != b for a, b in izip(s1, s2))

def pairwise(iterable):  # itertools recipe
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

inp = sys.argv[1]  # Input file

unique = defaultdict(list)
with open(inp, 'rb') as file:
    for fields in (line.strip().split('-') for line in file):
        id = '-'.join(fields[:-1])  # recombine all but last field into an id
        unique[id].append(fields[-1])  # accumulate ending fields with same id

for id in sorted(unique):
    final_fields = unique[id]
    final_fields.sort(key=lambda field: len(field))  # sort by length
    print id + ':' + '-'.join(final_fields)
    if len(final_fields) > 1:  # at least one pair to compare for mismatches?
        for a, b in pairwise(final_fields):
            if len(a) == len(b) and hamming_distance(a, b) < 2:
                print '  {!r} and {!r} differ by < 2 characters'.format(a, b)

輸出:

IGHV1-2:CARDSDYDWYFDLW-CAREGYNWNDEGRFDYW
IGHV1-2-IGHJ2:CARDSDYDWYFDLW
IGHV1-2-IGHJ4:CARDIAVPGHGDYW-CARRIGYSSGSEDYW-CAREGYNWNDEGRFDYW
IGHV1-8-IGHJ3:CARGQTYYDILTGPSDAFDIW
IGHV3-11-IGHJ:CATSGGSP
IGHV3-11-IGHJ4:CARDGDGYNDYW
IGHV3-23-IGHJ3:CAKWGPDAFDIW-CAKSGGWYLSDAFDIW-CAKSSGWYLSDAFDIW
  'CAKSGGWYLSDAFDIW' and 'CAKSSGWYLSDAFDIW' differ by < 2 characters
IGHV3-23-IGHJ4:CAKDWELYYFDYW-CAKDRGYTGYGVYFDYW-CAKDRGYTGFGVYFDYW
  'CAKDRGYTGYGVYFDYW' and 'CAKDRGYTGFGVYFDYW' differ by < 2 characters
IGHV3-23-IGHJ6:CAKEGCSSGCPYYYYGMDVW
IGHV3-9-IGHJ3:CANVPIYSSSYDAFDIW
IGHV4-39:CARSTGDWFDPW
IGHV4-39-IGHJ4:CARTGFGELGFDYW-CARHDILTGYSYYFDYW-CARHLGYNNSWYPFDYW-CARYLGYNSNWYPFDYW
IGHV4-39-IGHJ5:CARSTGDWFDPW
IGHV6-1-IGHJ4:CASGGAVPGYYFDYW

希望此更新對您有所幫助...

假設您要按A)列的長度,B)該列的Levenshtein距離與上方或下方的col進行排序。

問題立即表明,levenshtein距離在2個相對物體之間。 即, Levenshtein(a, b)不像len(a)這樣的單聲道屬性。 levenshtein距離的值隨着列表中各行相對於彼此位置的變化而變化。

Python 2.X支持較早的cmp vs key參數進行排序。 這是低效的,因為每次進行排序時都必須重新評估它。 但是,Levenshtein排序相對於條目上方和下方的項目。

例如,讓我們對示例數據進行矩陣處理:

txt='''\
IGHV3-23-IGHJ4  CAKDRGYTGYGVYFDYW
IGHV4-39-IGHJ4  CARHDILTGYSYYFDYW
IGHV3-23-IGHJ3  CAKSGGWYLSDAFDIW
IGHV4-39-IGHJ4  CARTGFGELGFDYW
IGHV1-2-IGHJ2   CARDSDYDWYFDLW
IGHV1-8-IGHJ3   CARGQTYYDILTGPSDAFDIW
IGHV4-39-IGHJ5  CARSTGDWFDPW
IGHV3-9-IGHJ3   CANVPIYSSSYDAFDIW
IGHV3-23-IGHJ4  CAKDWELYYFDYW
IGHV3-23-IGHJ4  CAKDRGYTGFGVYFDYW
IGHV4-39-IGHJ4  CARHLGYNNSWYPFDYW
IGHV1-2-IGHJ4   CAREGYNWNDEGRFDYW
IGHV3-23-IGHJ3  CAKSSGWYLSDAFDIW
IGHV4-39-IGHJ4  CARYLGYNSNWYPFDYW
IGHV3-23-IGHJ6  CAKEGCSSGCPYYYYGMDVW
IGHV3-23-IGHJ3  CAKWGPDAFDIW
IGHV3-11-IGHJ   CATSGGSP
IGHV3-11-IGHJ4  CARDGDGYNDYW
IGHV1-2-IGHJ4   CARRIGYSSGSEDYW
IGHV1-2-IGHJ4   CARDIAVPGHGDYW
IGHV6-1-IGHJ4   CASGGAVPGYYFDYW'''

data=[line.split() for line in txt.splitlines()] 
# [['IGHV3-23-IGHJ4', 'CAKDRGYTGYGVYFDYW'], ['IGHV4-39-IGHJ4', 'CARHDILTGYSYYFDYW'], ['IGHV3-23-IGHJ3', 'CAKSGGWYLSDAFDIW'], ['IGHV4-39-IGHJ4', 'CARTGFGELGFDYW'], ['IGHV1-2-IGHJ2', 'CARDSDYDWYFDLW'], ['IGHV1-8-IGHJ3', 'CARGQTYYDILTGPSDAFDIW'], ['IGHV4-39-IGHJ5', 'CARSTGDWFDPW'], ['IGHV3-9-IGHJ3', 'CANVPIYSSSYDAFDIW'], ['IGHV3-23-IGHJ4', 'CAKDWELYYFDYW'], ['IGHV3-23-IGHJ4', 'CAKDRGYTGFGVYFDYW'], ['IGHV4-39-IGHJ4', 'CARHLGYNNSWYPFDYW'], ['IGHV1-2-IGHJ4', 'CAREGYNWNDEGRFDYW'], ['IGHV3-23-IGHJ3', 'CAKSSGWYLSDAFDIW'], ['IGHV4-39-IGHJ4', 'CARYLGYNSNWYPFDYW'], ['IGHV3-23-IGHJ6', 'CAKEGCSSGCPYYYYGMDVW'], ['IGHV3-23-IGHJ3', 'CAKWGPDAFDIW'], ['IGHV3-11-IGHJ', 'CATSGGSP'], ['IGHV3-11-IGHJ4', 'CARDGDGYNDYW'], ['IGHV1-2-IGHJ4', 'CARRIGYSSGSEDYW'], ['IGHV1-2-IGHJ4', 'CARDIAVPGHGDYW'], ['IGHV6-1-IGHJ4', 'CASGGAVPGYYFDYW']]

現在將這些行按row[1]長度排序:

data.sort(key=lambda l: len(l[1])) 

現在根據條目的levenshtein距離進行排序。 請注意,由於levenstein基於兩個值,因此您需要使用cmp

data.sort(cmp=levenshtein)

# [['IGHV3-11-IGHJ', 'CATSGGSP'], ['IGHV4-39-IGHJ5', 'CARSTGDWFDPW'], ['IGHV3-23-IGHJ3', 'CAKWGPDAFDIW'], ['IGHV3-11-IGHJ4', 'CARDGDGYNDYW'], ['IGHV3-23-IGHJ4', 'CAKDWELYYFDYW'], ['IGHV4-39-IGHJ4', 'CARTGFGELGFDYW'], ['IGHV1-2-IGHJ2', 'CARDSDYDWYFDLW'], ['IGHV1-2-IGHJ4', 'CARDIAVPGHGDYW'], ['IGHV1-2-IGHJ4', 'CARRIGYSSGSEDYW'], ['IGHV6-1-IGHJ4', 'CASGGAVPGYYFDYW'], ['IGHV3-23-IGHJ3', 'CAKSGGWYLSDAFDIW'], ['IGHV3-23-IGHJ3', 'CAKSSGWYLSDAFDIW'], ['IGHV3-23-IGHJ4', 'CAKDRGYTGYGVYFDYW'], ['IGHV4-39-IGHJ4', 'CARHDILTGYSYYFDYW'], ['IGHV3-9-IGHJ3', 'CANVPIYSSSYDAFDIW'], ['IGHV3-23-IGHJ4', 'CAKDRGYTGFGVYFDYW'], ['IGHV4-39-IGHJ4', 'CARHLGYNNSWYPFDYW'], ['IGHV1-2-IGHJ4', 'CAREGYNWNDEGRFDYW'], ['IGHV4-39-IGHJ4', 'CARYLGYNSNWYPFDYW'], ['IGHV3-23-IGHJ6', 'CAKEGCSSGCPYYYYGMDVW'], ['IGHV1-8-IGHJ3', 'CARGQTYYDILTGPSDAFDIW']]

如果要將兩個元素排序cmp更改為鍵類型(對於不支持cmp的Python 3),則可以生成比較對象:

def cmp_to_key(mycmp):
    'Convert a cmp= function into a key= function'
    class K(object):
        def __init__(self, obj, *args):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        def __ne__(self, other):
            return mycmp(self.obj, other.obj) != 0
    return K 

您使用data.sort(key=cmp_to_key(levenshtein))排序

暫無
暫無

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

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