#python #dictionary
Вопрос:
Я очень новичок в Python и застрял на одной задаче. Сначала я сделал файл, содержащий несколько файлов fasta с именами последовательностей, в словарь, затем мне удалось выбрать только те, которые я хочу, на основе подстрок, включенных в ключи, которые определены в списке «flu_genes».
Теперь я пытаюсь изменить порядок элементов в этом словаре на основе порядка подстрок, определенных в списке «flu_genes». Я полностью застрял; я нашел способ переупорядочения на основе порядка ключей в списке, но это не мой случай, так как порядок определяется не ключами, а подстрокой внутри ключей. Следует также добавить, что в этом случае подстрока заканчивается форматом «_GENE», однако она может быть в середине строки с тем же форматом, возможно, «GENE«, поэтому я бы предпочел не полагаться на код для поиска подстроки в конце строки. Я надеюсь, что это достаточно ясно, и заранее благодарю за любую помощь!
"full_genome.fasta"
>A/influenza/1/1_NA
atgcg
>A/influenza/1/1_NP
ctgat
>A/influenza/1/1_FluB
agcta
>A/influenza/1/1_HA
tgcat
>A/influenza/1/1_FluC
agagt
>A/influenza/1/1_M
tatag
consensus = {}
flu_genes = ['_HA', '_NP', '_NA', '_M']
with open("full_genome.fasta", 'r') as myseq:
for line in myseq:
line = line.rstrip()
if line.startswith('>'):
key = line[1:]
else:
if key in consensus:
consensus[key] = line
else:
consensus[key] = line
flu_fas = {key : val for key, val in consensus.items() if any(ele in key for ele in flu_genes)}
print("Dictionary after removal of keys : " str(flu_fas))
>>>Dictionary after removal of keys : {'>A/influenza/1/1_NA': 'atgcg', '>A/influenza/1/1_NP': 'ctgat', '>A/influenza/1/1_HA': 'tgcat', '>A/influenza/1/1_M': 'tatag'}
#reordering by keys order (not going to work!) as in: https://try2explore.com/questions/12586065
reordered_dict = {k: flu_fas[k] for k in flu_genes}
Комментарии:
1. В строке проблемы вы пытаетесь использовать ключи, которые не являются ключами в словаре. Возможно, вы хотите создать словарь с этими ключами в качестве ключей, а остальные данные пусть будут вложенным словарем.
2. Как вы разбираете «A/грипп/1/1_NA»? Вам нужно сортировать или искать по какому-либо из полей или только по определенным? Вы когда-нибудь добавляли или удаляли данные из этой структуры данных?
3. @KennyOstrom спасибо. У меня есть текстовый файл, в котором каждая строка, начинающаяся с»>», является заголовком последовательности, а последующие строки-самой последовательностью, которая заканчивается перед следующим»>>», который будет отмечать заголовок второй последовательности. Файл будет содержать последовательности, не относящиеся к гриппу, поэтому мне нужно выбрать только те, которые содержат имена генов в заголовке последовательности, а также упорядочить их в соответствии с порядком списка «flu_genes». Я не буду добавлять данные. Также все имена генов, перечисленные в flu_genes, всегда будут присутствовать в файле
4. Похоже, что вы могли бы вытащить поле генов как часть исходного синтаксического анализа и сохранить все эти части в виде отдельных полей, сделав их доступными для других материалов. Но я думаю, что это выходит за рамки вопроса.
Ответ №1:
Словарь принципиально не отсортирован, но в качестве детали реализации python3 он запоминает порядок вставки, и вы не собираетесь ничего менять позже, так что вы можете делать то, что делаете.
Проблема, конечно, в том, что вы не работаете с реальными ключами. Поэтому давайте просто составим список ключей и отсортируем его в соответствии с вашими критериями. Затем вы можете сделать то же самое, что и раньше, за исключением использования настоящих ключей.
flu_genes = ['_HA', '_NP', '_NA', '_M']
def get_gene_index(k):
for index, gene in enumerate(flu_genes):
if k.endswith(gene):
return index
raise ValueError('I thought you removed those already')
reordered_keys = sorted(flu_fas.keys(), key=get_gene_index)
reordered_dict = {k: flu_fas[k] for k in reordered_keys}
for k, v in reordered_dict.items():
print(k, v)
A/грипп/1/1_HA tgcat
A/грипп/1/1_NP ctgat
A/грипп/1/1_NA atgcg
A/грипп/1/1_M татаг
Обычно я бы не делал сортировку по n-квадрату, но я предполагаю, что строки в файле данных намного больше, чем количество flu_genes, что делает это по существу фиксированной константой.
Это может быть или не быть лучшей структурой данных для вашего приложения, но я оставлю это на рассмотрение кода.
Комментарии:
1. Большое спасибо @Kenny Ostrom, это работает идеально. Надеюсь, в будущем это будет хорошая структура данных для меня.
Ответ №2:
Это потому, что вы пытаетесь изменить его порядок с помощью несуществующих ключей словаря. Ваши ключи
['>A/influenza/1/1_NA', '>A/influenza/1/1_NP', '>A/influenza/1/1_HA', '>A/influenza/1/1_M']
что не соответствует списку
['_HA', '_NP', '_NA', '_M']
сначала вам нужно преобразовать их, чтобы они совпали, и поскольку мы знаем, что шаблон находится в конце строки, начинающейся с подчеркивания, мы можем разделить их на подчеркивания и получить последнее совпадение.
consensus = {}
flu_genes = ['_HA', '_NP', '_NA', '_M']
with open("full_genome.fasta", 'r') as myseq:
for line in myseq:
line = line.rstrip()
if line.startswith('>'):
sequence = line
gene = line.split('_')[-1]
key = f"_{gene}"
else:
consensus[key] = {
'sequence': sequence,
'data': line
}
flu_fas = {key : val for key, val in consensus.items() if any(ele in key for ele in flu_genes)}
print("Dictionary after removal of keys : " str(flu_fas))
reordered_dict = {k: flu_fas[k] for k in flu_genes}
Комментарии:
1. Спасибо @Jen Chua, это отлично сработало! Однако теперь я потерял полные ключи, которые мне нужны, так как они будут именами последовательностей. Как я могу вернуть их в качестве ключей, имея в виду, что у меня будут сотни файлов с разными «полными ключами» (однако ключ = f»_{gene}» будет общим шаблоном). Является ли выполнение вложенного словаря ответом?
2. Вы также размещаете свои данные, если хотите сохранить дополнительные значения, такие как исходный ключ. Я обновил свой ответ.
3. Большое спасибо за вашу помощь. Ваше решение работает хорошо, однако ответ Кенни Острома создает единый словарь, с которым, я думаю, мне будет легче иметь дело.