Сравнение сходства вложенных списков - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть список из 3 списков, в каждом из которых есть по 1 списку.

data_set = [
    ['AB12345',['T','T','C','C','A','C','A','G','C','T','T','T','T','C']],
    ['AB12346',['T','T','C','C','A','C','C','G','C','T','C','T','T','C']],
    ['AB12347',['T','G','C','C','A','C','G','G','C','T','T','C','T','C']]
]

У меня есть метод сравнения, который даст мне сходство списка, который содержит символы, а не идентификатор.

def compare(_from, _to):
    similarity = 0
    length = len(_from)
    if len(_from) != len(_to):
        raise Exception("Cannot be compared due to different length.")
    for i in range(length):
        if _from[i] == _to[i]:
            similarity += 1
    return similarity / length * 100

compare(data_set[0][1], data_set[1][1])

Используя метод сравнения, я использовал цикл for для сравнения списка «a» с другими списками, как в случае сравнения «a» с «a», сравнения «a» с «b» и сравнения «a» с «с».

for i in range(len(data_set)):
    data_set[i].append(compare(data_set[0][1], data_set[i][1]))
    print(round(data_set[i][2], 2), end=", ")

Но после завершения сравнения 1-го списка с другими списками и с самим собой, как мне перейти к 2-му списку и 3-му списку и продолжить сравнение с другими списками, чтобы получить их сходство? Например, («b» сравнивают с «a», «b» сравнивают с «b» и «b» сравнивают с «c») и («c» сравнивают с «a», «c» сравнивают с «b» и "c" сравнить с "c").

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Для дальнейшего использования лучше включить свои списки ввода (a, b, c) в свой код, а не использовать снимок экрана, чтобы избавить людей от необходимости печатать целые списки. Я использовал несколько более коротких версий для тестирования.

Вы можете сделать что-то вроде следующего, чтобы перебрать оба списка и сравнить результаты. Это аккуратнее, чем при использовании for i in range(len(data_set)):

# Make some test data
a= ["ID_A", ['T', 'G', 'A']]
b= ["ID_B", ['T', 'C', 'A']]
c= ["ID_C", ['C', 'A', 'A']]

data = [a,b,c]

# entry1 takes each of the values a,b,c in order, and entry2 will do the same,
# so you'll have all possible combinations.
for entry1 in data:
    for entry2 in data:
        score = compare(entry1[1], entry2[1])
        print("Compare ", entry1[0], " to ", entry2[0], "Score :", round(score))

Выход:

Compare  ID_A  to  ID_A  Score : 100
Compare  ID_A  to  ID_B  Score : 67
Compare  ID_A  to  ID_C  Score : 33
Compare  ID_B  to  ID_A  Score : 67
Compare  ID_B  to  ID_B  Score : 100
Compare  ID_B  to  ID_C  Score : 33
Compare  ID_C  to  ID_A  Score : 33
Compare  ID_C  to  ID_B  Score : 33
Compare  ID_C  to  ID_C  Score : 100

Возможно, вам лучше хранить результаты в другом массиве, чем тот, в котором вы храните свои списки.

0 голосов
/ 09 ноября 2018

Вы также можете использовать itertools.combinations для сравнения всех ваших подсписков. Кроме того, в вашей функции compare() вы можете рассмотреть возможность возврата значения, которое указывает, что подсписки несопоставимы, а не создавать исключение, чтобы не допустить преждевременного замыкания цикла при сравнении большего набора подсписков.

Ниже приведен пример (также включает немного более простую версию вашей функции compare(), которая возвращает -1, когда списки несопоставимы из-за длины, но не выполняет сравнение списка с самим собой, поскольку возвращаемое значение будет всегда быть 100 в этой ситуации и, кажется, пустая трата производительности).

import itertools

data_set = [
    ['AB12345',['T','T','C','C','A','C','A','G','C','T','T','T','T','C']],
    ['AB12346',['T','T','C','C','A','C','C','G','C','T','C','T','T','C']],
    ['AB12347',['T','G','C','C','A','C','G','G','C','T','T','C','T','C']]
    ]

def compare(a, b):
    length = len(a) if len(a) == len(b) else 0
    similarity = sum(1 for i in range(length) if a[i] == b[i])
    return similarity / length * 100 if length else -1

for a, b in itertools.combinations(data_set, 2):
    compared = a[0] + ' and ' + b[0]
    result = compare(a[1], b[1])
    print(f'{compared}: {result}')

# OUTPUT
# AB12345 and AB12346: 85.71428571428571
# AB12345 and AB12347: 78.57142857142857
# AB12346 and AB12347: 71.42857142857143
0 голосов
/ 09 ноября 2018

Просто используйте второй вложенный цикл, подобный этому

for i in range(len(data_set)):
    for j in range(len(data_set)):
        data_set[i].append(compare(data_set[j][1], data_set[i][1]))
        print(round(data_set[i][2], 2), end=", ")
...