【问题标题】:Convert nltk Tree to JSON representation将 nltk 树转换为 JSON 表示
【发布时间】:2014-04-16 14:24:45
【问题描述】:

我想将以下 nltk 树表示形式转换为 JSON 格式:

期望的输出:

{
    "scores": {
        "filler": [
            [
                "scores"
            ],
            [
                "for"
            ]
        ],
        "extent": [
            "highest"
        ],
        "team": [
            "India"
        ]
    }
}

【问题讨论】:

  • 它不是一个有效的 JSON:同一个对象中有两个“团队”名称。 JSON 对象是一组无序的名称/值对。不同的 json 解析器可能会产生不同的结果:解析器可能只保留第一个“团队”,或者只保留最后一个“团队”对,或者(不太可能)create a list ["India", "Pakistan"]
  • 另见rfc 7159“当对象中的名称不唯一时,接收此类对象的软件的行为是不可预测的。许多实现只报告姓氏/值对. 其他实现报告错误或无法解析对象,并且一些实现报告所有名称/值对,包括重复项。"
  • 源代码树再次包含重复的名称('filler', 'filler') 为什么要从输出中删除它们?
  • 它在构建字典时被自动删除。可以将它们删除,因为输出中不需要填充信息。
  • 你怎么知道输出中不需要它?

标签: python json tree nltk


【解决方案1】:

看起来输入树可能包含同名的孩子。为了支持一般情况,您可以将每个 Tree 转换为将其名称映射到其子列表的字典:

from nltk import Tree # $ pip install nltk

def tree2dict(tree):
    return {tree.node: [tree2dict(t)  if isinstance(t, Tree) else t
                        for t in tree]}

例子:

import json
import sys

tree = Tree('scores',
            [Tree('extent', ['highest']),
             Tree('filler',
                  [Tree('filler', ['scores']),
                   Tree('filler', ['for'])]),
             Tree('team', ['India'])])
d = tree2dict(tree)
json.dump(d, sys.stdout, indent=2)

输出:

{
  "scores": [
    {
      "extent": [
        "highest"
      ]
    }, 
    {
      "filler": [
        {
          "filler": [
            "scores"
          ]
        }, 
        {
          "filler": [
            "for"
          ]
        }
      ]
    }, 
    {
      "team": [
        "India"
      ]
    }
  ]
}

【讨论】:

    【解决方案2】:

    将 Tree 转换为 dict,然后再转换为 JSON。

    def tree_to_dict(tree):
        tdict = {}
        for t in tree:
            if isinstance(t, nltk.Tree) and isinstance(t[0], nltk.Tree):
                tdict[t.node] = tree_to_dict(t)
            elif isinstance(t, nltk.Tree):
                tdict[t.node] = t[0]
        return tdict
    
    def dict_to_json(dict):
        return json.dumps(dict)
    
    output_json = dict_to_json({tree.node: tree_to_dict(tree)})
    

    【讨论】:

    • tree转换成dict并使用json.dump(result_dict, sys.stdout, indent=2)而不是手动生成json文本。
    • 谢谢。将再次调查。
    • @J.F.Sebastian 如何将树转换为字典?我应该使用哪种方法?
    • t.node 现在必须切换到 t.label()。对于“汤姆布拉迪为爱国者队效力”这句话。输出为:{'ORGANIZATION': ('Patriots', 'NNP'), 'PERSON': ('Brady', 'NNP')}
    【解决方案3】:

    将树转换为以树标签为键的字典,然后您可以使用 JSON 转储轻松将其转换为 JSON

        import nltk.tree.Tree
    
        def tree_to_dict(tree):
            tree_dict = dict()
            leaves = []
            for subtree in tree:
                if type(subtree) == nltk.tree.Tree:
                    tree_dict.update(tree_to_dict(subtree))
                else:
                    (expression,tag) = subtree
                    leaves.append(expression)
            tree_dict[tree.label()] = " ".join(leaves)
    
            return tree_dict
    

    【讨论】:

    • 作为比较点,这会为句子“Tom Brady Plays for the Patriots”输出{'ORGANIZATION': 'Patriots', 'PERSON': 'Brady', 'S': 'plays for the .'}
    【解决方案4】:

    一个相关的替代方案。出于我的目的,我不需要保留确切的树,而是想将实体提取为键,将标记提取为值列表。对于“汤姆和拉里为爱国者队效力”这句话。我想要以下 JSON:

    {
      "PERSON": [
        "Tom",
        "Larry"
      ],
      "ORGANIZATION": [
        "Patriots"
      ]
    }
    

    这保留了标记的顺序(每个实体类型),同时也不会“踩踏”为实体键设置的值。您可以在其他答案中重复使用相同的json.dump 代码,将此字典返回到 json。

    from nltk import tag,chunk,tokenize
    
    def prep(sentence):
        return chunk.ne_chunk(tag.pos_tag(tokenize.word_tokenize(sentence)))
    
    t = prep("Tom and Larry play for the Patriots.")
    
    def tree_to_dict(tree):
        tree_dict = dict()
        for st in tree:
            # not everything gets a NE tag,
            # so we can ignore untagged tokens
            # which are stored in tuples
            if isinstance(st, nltk.Tree):
                if st.label() in tree_dict:
                    tree_dict[st.label()] = tree_dict[st.label()] + [st[0][0]]
                else:
                    tree_dict[st.label()] = [st[0][0]]
        return tree_dict
    
    print(tree_to_dict(t))
    # {'PERSON': ['Tom', 'Larry'], 'ORGANIZATION': ['Patriots']}
    

    【讨论】:

      猜你喜欢
      • 2015-12-09
      • 2014-01-16
      • 2017-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-08
      相关资源
      最近更新 更多