Вложено для цикла с условием if в xml, Python - PullRequest
0 голосов
/ 24 февраля 2019

Я хочу вернуть AA_code, когда пользователь вводит CHAIN_ID и RES_POSITION.CHAIN_ID является подэлементом тега CHAIN, а RES_POSITION и AA_CODE являются подэлементами тега RESIDUE.Тег RESIDUE также является подэлементом тега CHAIN.

Мой код возвращает AA_CODE только для CHAIN_ID = "A" и до RES_POSITION = "370".Однако он не возвращается для других CHAIN_IDs, но должен возвращаться.Я не мог понять причину, по которой любая помощь будет оценена.

PS: я использую Elementtree.

Пример XML:

<RESIDUE>
         <RES_POSITION>370</RES_POSITION>
         <AA_CODE>G</AA_CODE>
      </RESIDUE>
   </CHAIN>
   <CHAIN>
      <CHAIN_ID>B</CHAIN_ID>
      <RESIDUE>
         <RES_POSITION>371</RES_POSITION>
         <AA_CODE>S</AA_CODE>
      </RESIDUE>

Мой кодкоторый возвращает истинный результат:

   chain = [seq for seq in SEQ.findall('CHAIN') if seq.findtext('CHAIN_ID') == "A"]
    print(chain)
    sequence = [res for res in SEQ.find('CHAIN') if res.findtext('RES_POSITION') == "370"]
    print(sequence)
    for seq in chain:
            for res in sequence:
                if res in seq:
                    print(res.findtext('AA_CODE'))

Возвращает:

[<Element 'CHAIN' at 0x0000019203C83138>]
        [<Element 'RESIDUE' at 0x00000192040E4C78>]
        G

Мой код для CHAIN_ID как B:

chain = [seq for seq in SEQ.findall('CHAIN') if seq.findtext('CHAIN_ID') == "B"]
print(chain)
sequence = [res for res in SEQ.find('CHAIN') if res.findtext('RES_POSITION') == "371"]
print(sequence)
for seq in chain:
        for res in sequence:
            if res in seq:
                print(res.findtext('AA_CODE'))

Возвращает:

[<Element 'CHAIN' at 0x000002EFB2254DB8>]
[]

1 Ответ

0 голосов
/ 24 февраля 2019
sequence = [res for res in SEQ.find('CHAIN') if res.findtext('RES_POSITION') == "371"]

Здесь вы пишете SEQ.find(...) вместо SEQ.findall(...).

Это то, что вы намеревались?find () находит только первое вхождение CHAIN ​​в вашем XML-файле, и я предполагаю, что вторая часть строки (res_position == 371) будет иметь значение False для найденного элемента, поэтому последовательность будет пустойlist.

Кроме того, пока findall возвращает элементы CHAIN, findall возвращает только подэлементы CHAIN, для чего требуется адаптация if-части оператораогенератора.

Вот некоторый код, который я 'мы действительно протестировали; -):

chain = [seq for seq in SEQ.findall('CHAIN') if seq.findtext('CHAIN_ID') == "B"]
print(chain)
sequence = [res for res in SEQ.findall('CHAIN') if res.findtext('RESIDUE/RES_POSITION') == "371"]
print(sequence)
for seq in chain:
    for res in sequence:
        if res == seq:
            print("=> %s" % res.findtext('RESIDUE/AA_CODE'))
  • Поскольку строка последовательности теперь содержит элементы CHAIN, вам необходимо найти элементы RES_POSITION и AA_CODE, добавив префикс имени элемента RESIDUE.
  • По той же причине вы проверяете res и seq на равенство, а не на «сдержанность» (это слово?).

Еще одно предложение - попробуйте это:

chain = [
    seq for seq in SEQ.findall('CHAIN')
    if seq.findtext('CHAIN_ID') == "B"
        and seq.findtext('RESIDUE/RES_POSITION') == "371"
] 
for seq in chain:
    print("=> %s" % seq.findtext('RESIDUE/AA_CODE'))

Это гораздо эффективнее, потому что он проходит только один раз по всем вашим данным и не требует вложенного цикла for.

...