【问题标题】:Creating dictionary from XML file从 XML 文件创建字典
【发布时间】:2014-10-31 05:54:08
【问题描述】:

我有一个看起来像这样的 XML 文件:

<?xml version="1.0" encoding ="utf8"?>
<rebase>
  <Organism>
    <Name>Aminomonas paucivorans</Name>
      <Enzyme>M1.Apa12260I</Enzyme>
        <Motif>GGAGNNNNNGGC</Motif>
      <Enzyme>M2.Apa12260I</Enzyme>
        <Motif>GGAGNNNNNGGC</Motif>
  </Organism>
  <Organism>
    <Name>Bacillus cellulosilyticus</Name>
      <Enzyme>M1.BceNI</Enzyme>
        <Motif>CCCNNNNNCTC</Motif>
      <Enzyme>M2.BceNI</Enzyme>
        <Motif>CCCNNNNNCTC</Motif>
  </Organism>

对于每个Organism,有多个EnzymesMotifs。酶是独一无二的,但基序可以重复。所以我尝试创建一个以酶为键,以主题为值的字典。这是我的代码:

    import xml.etree.ElementTree as ET

    def lister():
        tree = ET.parse('rebase.xml')
        rebase = tree.getroot()

        data_dict = {}

        for each_organism in rebase.findall('Organism'):
            try:
                enzyme = each_organism.find('Enzyme').text
            except AttributeError:
                continue

            for motif in each_organism.findall('Motif'):
                motif = motif.text
                data_dict[enzyme] = motif
        return data_dict

然而,字典似乎省略了相当多的条目。我似乎可以理解问题所在。任何帮助将不胜感激。

编辑

一个用户发了一个解决方案,后来又删了,不过我可以及时复制:

for each_organism in rebase.findall('Organism'):
        try:
            enzyme = each_organism.find('Enzyme').text
        except AttributeError:
            continue
        data_dict[enzyme] = []
        for motif in each_organism.findall('Motif'):
            data_dict[enzyme].append(motif.text)
    return data_dict

但是在这种情况下返回的字典是错误的,原因如下:

酶-基序对是独一无二的。这样 1 种酶只有 1 个基序。在我的文件中,一个酶只出现一次,一个基序可以出现多次,但它属于不同的酶,所以这对是独一无二的。 EDIT 下的代码是这样的:

假设和酶 - M.APaI 带有主题 GATC 和另一个 M.APaII 带有主题 TCAG。两种酶非常相似(仅在最后一个字符I 上有所不同)。该代码将两个基序与第一个酶结合,产生{M.ApaI :['GATC','TCAG']}

【问题讨论】:

  • 您似乎只在每个生物体中寻找第一个Enzyme,然后遍历所有Motifs,无论它们是否属于该酶。你确定这是对的吗?然后(这会导致数据丢失)您覆盖Enzyme 的所有Motifs - 但即使您构建所有Motifs 的列表,它们仍然会绑定到错误的Enzyme.. .

标签: python xml dictionary


【解决方案1】:

我看到的第一个大问题是您只在任何给定有机体中寻找第一个酶。如果你想找到每个 Enzyme 的发生率,你应该使用:

 for enzyme in each_organism.findall('Enzyme'):
     # add to dictionary here

第二个问题是您的 XML 格式与您似乎使用字典构建的数据关系不匹配。在 XML 中,Enzyme、Motif 和 Name 都是 Organism 的子项,但您将 motif 指定为与​​酶键关联的值。在遍历事件发生率时,您无法知道哪一个应该与另一个关联,因为它们都被挤在一起,对象中没有任何逻辑分离。

我可能误解了您在这里的目的,但似乎最好通过构造 Organism 和 Enzyme 类对象而不是将两个(显然)不相关的概念强制为键值关系。

这可能看起来像这样,并封装您的字段:

class Organism:
    # where enzymes is an iterable of Enzyme
    def __init__(self, name, enzymes):
        self.name = name
        self.enzymes = enzymes

还有你的 Enzyme 对象:

class Enzyme:
    # where motifs is an iterable of string
    def __init__(self, motifs):
        self.motifs = motifs

所有这些仍然需要对您的 XML 文件进行某种更改。除非您只是逐行解析它(这绝对不是 XML 的重点),否则我想不出任何简单的方法可以让您立即找出哪些 Motif 属于哪个 Enzyme。

编辑:看到您在询问通过每个 Enzyme 节点相当盲目地迭代的方法,并假设您始终有一个 Name 元素,每个 Enzyme 都有一个 Motif,并且 Name 之后的每个元素都是 Enzymes然后 Motif(例如 E-M-E-M 等)你应该能够做到这一点:

i = 0
enzymes = []
motifs = []

for element in each_organism:
    # skip the first Name child
    if i == 0:
        continue
    # if we're at an odd index, indicating an enzyme
    if i % 2 == 1:
        enzymes.append(element.text)
    # if we're at an even index, indicating the related motif
    elif i % 2 == 0:
        motifs.append(element.text)

    i += 1

然后,假设我提出的每一个假设,可能还有更多(我什至不能 100% 确定 etree 总是自上而下地迭代元素),任何给定的任何主题都是正确的基序中的索引将属于酶中相同索引的酶。如果我还没有说清楚:这是非常脆弱的代码。

【讨论】:

  • 是否有一种粗略的方法可以逐行读取文件并将每个酶和基序聚集为键值对(如果它们同时出现)?我知道这会破坏 XML 格式的全部目的,但它会起作用
  • @Beginner 好吧,根据我更好的判断,我已经制定了一种您可能会完成的方法。不过,请记住我的警告。
  • 谢谢。我有类似的东西,似乎正在工作。
  • @Beginner 如果对您有帮助,如果您能选择答案,那就太好了。
猜你喜欢
  • 2014-09-09
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 2013-12-06
  • 1970-01-01
  • 2011-10-08
  • 2012-12-15
  • 2018-03-29
相关资源
最近更新 更多