#python-3.x
#python-3.x
Вопрос:
У меня есть словарь, такой как :
dict = {'group1':["-----AGAAC--C--","-----ATATA-----"],'group2':["------AGGCGGA----","--AAACC----------","--AAACCG---------"]}
в этом словаре я хотел бы сравнить все значения друг с другом, выполнив итерацию всех из них.
Идея состоит в том, чтобы сравнивать каждое значение и подсчитывать, когда буква стоит перед символом, отличным от буквенного.
Вот результаты, которые я должен получить (номер буквы, перед которой стоит символ, отличающийся от альфа (характеризуемый pipe
в приведенном ниже примере) / длина строки)
группа1:
элемент1 против элемента2
-----AGAAC--C--
-----*****--|--
-----ATATA-----
1/15 = 0.07
группа2:
элемент 1 против элемента 2
------AGGCGGA----
--||||*||||||----
--AAACC----------
10/17= 0.59
элемент 2 против элемента 3
--AAACC----------
--*****|---------
--AAACCG---------
1/17= 0.059
элемент 1 против элемента 3
------AGGCGGA----
--||||**|||||----
--AAACCG---------
9/17=0.53
Вот код, который я использую для их сравнения и вычисления оценки для группы1:
value1="-----AGAAC--C--"
value2="-----ATATA-----"
count=0
for a,b in zip(value1,value2):
print(a.isalpha(),b.isalpha())
if a.isalpha() == True and b.isalpha()==False:
count = 1
if a.isalpha()==False and b.isalpha()== True :
count =1
print(count/len(value1))
но мне не удается сделать это для всех значений автоматически… У кого-нибудь есть идея?
Спасибо за вашу помощь.
Ответ №1:
Вот способ сделать это:
from itertools import combinations
# Input data
dict = {
'group1': ['-----AGAAC--C--', '-----ATATA-----'],
'group2': ['------AGGCGGA----', '--AAACC----------', '--AAACCG---------']
}
# Iterate groups
for group, elements in dict.items():
# Print group name
print(group)
# Iterate every pair of elements
for element1, element2 in combinations(elements, 2):
# Check both elements have the same length
n = len(element1)
if len(element2) != n:
raise ValueError
# Count the number of times character types do not match
count = sum(c1.isalpha() != c2.isalpha() for c1, c2 in zip(element1, element2))
# Compute ratio
ratio = count / n
# Print result
print(f' * {element1} vs {element2}: {ratio:.4f} ({count}/{n})')
print()
Вывод:
group1
* -----AGAAC--C-- vs -----ATATA-----: 0.0667 (1/15)
group2
* ------AGGCGGA---- vs --AAACC----------: 0.5882 (10/17)
* ------AGGCGGA---- vs --AAACCG---------: 0.5294 (9/17)
* --AAACC---------- vs --AAACCG---------: 0.0588 (1/17)
РЕДАКТИРОВАТЬ: Если вы хотите собрать список пар, которые дают оценку выше некоторого порога, вы можете немного изменить приведенный выше код:
from itertools import combinations
dict = {
'group1': ['-----AGAAC--C--', '-----ATATA-----'],
'group2': ['------AGGCGGA----', '--AAACC----------', '--AAACCG---------']
}
threshold = 0.10
interesting_pairs = []
for group, elements in dict.items():
for element1, element2 in combinations(elements, 2):
n = len(element1)
if len(element2) != n:
raise ValueError
count = sum(c1.isalpha() != c2.isalpha() for c1, c2 in zip(element1, element2))
ratio = count / n
if ratio > threshold:
interesting_pairs.append((element1, element2))
print(interesting_pairs)
# [('------AGGCGGA----', '--AAACC----------'), ('------AGGCGGA----', '--AAACCG---------')]
РЕДАКТИРОВАТЬ 2: Следуя обсуждению в комментариях, вот еще один вариант, который группирует элементы с коэффициентом, превышающим некоторый порог, транзитивно. На самом деле это еще одна отдельная проблема, а именно поиск связанных компонентов графика, заданного этим отношением. Вы можете сделать это, например, с помощью поиска в глубину:
from itertools import combinations
dict = {
'group1': ['-----AGAAC--C--', '-----ATATA-----'],
'group2': ['------AGGCGGA----', '--AAACC----------', '--AAACCG---------']
}
threshold = 0.10
# Find connected elements
connected = {}
for group, elements in dict.items():
for element1, element2 in combinations(elements, 2):
n = len(element1)
if len(element2) != n:
raise ValueError
count = sum(c1.isalpha() != c2.isalpha() for c1, c2 in zip(element1, element2))
ratio = count / n
if ratio > threshold:
connected.setdefault(element1, {element1}).add(element2)
connected.setdefault(element2, {element2}).add(element1)
# Search components with DFS
result = []
visited = set()
for elem, conn in connected.items():
if elem in visited:
continue
visited.add(elem)
conn = set(conn)
pending = list(conn)
while pending:
subelem = pending.pop()
if subelem in visited:
continue
visited.add(subelem)
subconn = connected[subelem]
conn.update(subconn)
pending.extend(subconn)
result.append(conn)
print(result)
# [{'------AGGCGGA----', '--AAACCG---------', '--AAACC----------'}]
Комментарии:
1. Ого, спасибо, я не ожидал чего-то подобного. Спасибо за ваше время 🙂
2. Есть ли у вас идея, как я мог бы поместить, например, все элементы, которые имеют отношение > 0.10, в новый список list вместе? например, поместите
------AGGCGGA----
,--AAACC----------
и--AAACCG---------
вместе в такой список (и то же самое для group1), как :list1 = [["------AGGCGGA----" , "--AAACC----------", "--AAACCG---------"],["-----AGAAC--C--","-----ATATA----"]
3. @chippycentra Я не уверен, что понимаю, что вы имеете в виду,
list1
определенный вами файл содержит все элементы вgroup2
иgroup1
.4. Ho извините, на самом деле я хотел бы создать новый список и внутри этого списка создать список пар последовательностей, которые имеют отношение
> 0.10
. Итак, здесь, в этом примере, если соотношение между------AGGCGGA---- vs --AAACCG---------
становится0.005
вместо0.5294
и-----AGAAC--C-- vs -----ATATA-----
становится0.5
вместо0.0667
list1 = [["------AGGCGGA----" , "--AAACC----------"],"[-----AGAAC--C--","-----ATATA-----"]]
, я должен получить список, такой как:, , , но в реальном примере я должен получить :list1 = [["------AGGCGGA----" , "--AAACC----------", "--AAACCG---------"]]
5. @chippycentra Я добавил вариант решения, я не уверен, что это то, чего вы добивались.