繁体   English   中英

xml 到 dataframe 与 python 的严重嵌套

[英]heavily nested xml to dataframe with python

提示:本站为国内最大中英文翻译问答网站,提供中英文对照查看,鼠标放在中文字句上可显示英文原文

我有一个嵌套很深的 xml,我正在尝试将其转换为数据框 object。

下面附上失败的尝试。

输入:johnny.xml 文件,包含以下文本-

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE collection SYSTEM "BioC.dtd">
<collection>
  <source/>
  <date/>
  <key/>
  <document>
    <id>2301222206</id>
    <infon key="tt_curatable">no</infon>
    <infon key="tt_version">1</infon>
    <infon key="tt_round">1</infon>
    <passage>
      <offset>0</offset>
      <text>Johnny likes pizza and chocolate, he lives in Italy with Emily.</text>
      <annotation id="1">
        <infon key="type">names</infon>
        <infon key="identifier">first_name</infon>
        <infon key="annotator">annotator_1</infon>
        <infon key="updated_at">2023-01-22T22:12:56Z</infon>
        <location offset="0" length="6"/>
        <text>Johnny</text>
      </annotation>
      <annotation id="3">
        <infon key="type">food</infon>
        <infon key="identifier"></infon>
        <infon key="annotator">annotator_2</infon>
        <infon key="updated_at">2023-01-22T22:13:51Z</infon>
        <location offset="13" length="19"/>
        <text>pizza and chocolate</text>
      </annotation>
      <annotation id="4">
        <infon key="type">location</infon>
        <infon key="identifier">europe</infon>
        <infon key="annotator">annotator_2</infon>
        <infon key="updated_at">2023-01-22T22:14:05Z</infon>
        <location offset="46" length="5"/>
        <text>Italy</text>
      </annotation>
      <annotation id="2">
        <infon key="type">names</infon>
        <infon key="identifier">first_name</infon>
        <infon key="annotator">annotator_1</infon>
        <infon key="updated_at">2023-01-22T22:13:08Z</infon>
        <location offset="57" length="5"/>
        <text>Emily</text>
      </annotation>
    </passage>
  </document>
</collection>

所需 output: 在此处输入图像描述

失败的尝试:

  • 与 lxml
from lxml import objectify
root = objectify.parse('johnny.xml').getroot()
data=[]
for i in range(len(root.getchildren())):
    data.append([child.text for child in root.getchildren()[i].getchildren()])
df = pd.DataFrame(data)

结果 -

    0   1   2   3   4
0   None    None    None    None    None
1   None    None    None    None    None
2   None    None    None    None    None
3   2301222206  no  1   1   None
id  infon-1 infon-2 infon-3 infon-key-1 infon-key-2 infon-key-3 passage-offset  passage-text    passage-annotation-id-1 ... passage-annotation-location-offset-3    passage-annotation-location-offset-4    passage-annotation-location-length-1    passage-annotation-location-length-2    passage-annotation-location-length-3    passage-annotation-location-length-4    passage-annotation-text-1   passage-annotation-text-2   passage-annotation-text-3   passage-annotation-text-4
0   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3   2301222206  no  1   1   tt_curatable    tt_version  tt_round    0   Johnny likes pizza and chocolate, he lives in Italy with Emily. 1   ... 46  57  6   19  5   5   Johnny  pizza and chocolate Italy   Emily

    4 rows × 56 columns
import pandas_read_xml as pdx
p2 = 'Johnny.xml'
df = pdx.read_xml(p2, ['collection'])
df = pdx.fully_flatten(df)
df

结果生成了 47 行,这也不是我想要的。

谢谢!

这是一个使用pandasxmltodict的例子

import pandas as pd
import xmltodict
from   pathlib import Path

xmldict = xmltodict.parse(Path("johnny.xml").read_text())

# unpack the names/text content from document.infon
xmldict["collection"]["document"]["infon"] = dict(
   list(row.values()) 
   for row in xmldict["collection"]["document"]["infon"]
)   

# unpack the names/text content from annotation dicts
xmldict["collection"]["document"]["passage"]["annotation"] = [
   { key: val for key, val in row.items() if key != "infon" } | 
   { col["@key"]: col.get("#text") for col in row["infon"] } 
   for row in xmldict["collection"]["document"]["passage"]["annotation"]
]

# use `.json_normalize()` to create a dataframe 
# `.explode()` turns each annotation into its own row
df = (
   pd.json_normalize(xmldict)
     .explode("collection.document.passage.annotation")
)

# remove annotations column 
# use `.json_normalize()` to create dataframe from annotation dicts
# concat/combine the columns with original dataframe
df = pd.concat(
   [
      df.drop(columns="collection.document.passage.annotation"),
      pd.json_normalize(df["collection.document.passage.annotation"])
        .set_index(df.index)
   ],
   axis=1
)

您可以根据需要重命名/删除列:

>>> df.columns
Index(['collection.source', 'collection.date', 'collection.key',
       'collection.document.id', 'collection.document.infon.tt_curatable',
       'collection.document.infon.tt_version',
       'collection.document.infon.tt_round',
       'collection.document.passage.offset',
       'collection.document.passage.text',
       '@id', 'text', 'type', 'identifier', 'annotator', 'updated_at', 
       'location.@offset', 'location.@length'],
      dtype='object')
>>> df[["@id", "text", "type", "identifier"]]
  @id                 text      type  identifier
0   1               Johnny     names  first_name
0   3  pizza and chocolate      food        None
0   4                Italy  location      europe
0   2                Emily     names  first_name

[更新]:

使用|的可能替代方法

for row in xmldict["collection"]["document"]["passage"]["annotation"]:
   row.update(
      { col["@key"]: col.get("#text") for col in row["infon"] } 
   )
   row.pop("infon", None)

发生的事情是row来自:

{'@id': '1', 
 'infon': [
    {'@key': 'type', '#text': 'names'}, 
    {'@key': 'identifier', '#text': 'first_name'}, 
    {'@key': 'annotator', '#text': 'annotator_1'}, 
    {'@key': 'updated_at', '#text': '2023-01-22T22:12:56Z'}],
 'location': {'@offset': '0', '@length': '6'}, 
 'text': 'Johnny'}

进入:

{'@id': '1', 
 'type': 'names',
 'identifier': 'first_name',
 'annotator': 'annotator_1',
 'updated_at': '2023-01-22T22:12:56Z',
 'location': {'@offset': '0', '@length': '6'}, 
 'text': 'Johnny'}

row["infon"]中的每个字典都被“解包”,键/文本值被“合并”到顶层。

然后infon密钥。

xmltodict使用@key / #text的原因是为了避免名称冲突。

如果在此示例中有内部{"@key": "text", ...} ,将其合并到顶层将覆盖现有的"text": "Johnny"

如果这是一个问题,您可以预先添加annotation. 键,所以你最终得到的是:

{'@id': '1',
 'annotation.type': 'names',
 'annotation.identifier': 'first_name',
 'annoation.annotator': 'annotator_1',
 'annotation.updated_at': '2023-01-22T22:12:56Z',
 'location': {'@offset': '0', '@length': '6'},
 'text': 'Johnny'}

这可能是我在最初的例子中应该做的。

问题未解决?试试本站强大的搜索功能,搜索: xml 到 dataframe 与 python 的严重嵌套
将严重嵌套的 json 文件转换为 R/Python dataframe

[英]Convert heavily nested json file into R/Python dataframe

我在 stackoverflow 上发现了很多类似的问题,但是,我仍然没有解决一个问题。 我有一个嵌套很深的“.json”文件,我需要将其导入并转换为 R 或 Python data.frame才能使用。 Json 文件包含内部列表(通常为空但有时包含数据)。 json的结构示例: 我使用R ...

在python中解析高度嵌套的JSON

[英]Parsing heavily nested JSON in python

我正在通过API连接并提取JSON,但无法进行解析。 我已经能够解析到以下示例级别。 我想从生成的JSON列表中提取“符号”列表,但似乎只能对单个实体执行此操作。 如果可能的话,我想直接这样做(即避免只使用循环)。 即,这有效: 返回此: 但是,这并没有: ...

从Pandas中高度嵌套的JSON创建DataFrame吗?

[英]Create a DataFrame from a heavily nested JSON in Pandas?

我有一个深层嵌套的JSON文件,该文件取自IBM的个性分析工具。 我可以用它创建DataFrame的最短方法是什么。 父“键”是否在多行中重复都没有关系 。 我可以使用多重索引使其看起来不错。 我主要关心的是将JSON散布到数据帧中。 这是JSON的链接: https : //api. ...

以“重嵌套”结构对Python OrderedDict进行排序

[英]Sorting Python OrderedDict in “heavily nested” structure

我有以下Python字典,并尝试将其排序为OrderedDict。 基本上,我想通过每个appleType的“ sort”值对该子词典中的不同appleType进行排序。 最后,理想情况下,有序字典应如下所示: 我一直在使用sorted函数,但是我不太正确,我不确定如何在嵌套结 ...

大量嵌套数据时如何使用python获取信息

[英]How to get information with python when data is heavily nested

我有一个文本文件,其中包含一些要挖掘的数据。 结构如下图所示 在某人的记录中,子字段不存在,在这种情况下,输出应指定子字段未知。 现在下面是我用来提取数据的代码 输出如下所示 问题是我不知道在哪里打印数据,所以目前我正在使用以下陈述打印数据,这是错误的 如 ...

将 XML 嵌套到 Pandas 数据框

[英]Nested XML to Pandas dataframe

我正在尝试创建一个脚本来将嵌套的 XML 文件转换为 Pandas 数据框。 我发现这篇文章https://medium.com/@robertopreste/from-xml-to-pandas-dataframes-9292980b1c1c ,它在进入第二级(父母,孩子)方面做得很好,但我不知道 ...

将嵌套的 XML 解析为 DataFrame

[英]Parse nested XML into DataFrame

我从 XML 形式的 API 收到回复。 看起来像: 我需要将每个标签下的数据转换为 pandas dataframe 的形式: 我已经尝试过 ElementTree,但到目前为止我的所有尝试都失败了。 ...

重嵌套循环中的随机生成

[英]Random generation in heavily nested loops

我有一个小游戏正在为一个学校项目制作,直到现在为止都已经完成了。 我为多个屏幕使用了一个非常混乱的嵌套列表系统,每个系统都有一个用于屏幕上对象的2D数组。 这些2D“级别”阵列也排列在它们自己的2D阵列中,从而构成“世界”。 这些字符串对应于使用pygame绘制的对象图块。 我的 ...

使用 python 将深度嵌套的 XML 解析为数据帧 - 努力处理更深层次的元素

[英]Parsing deeply nested XML into dataframe with python - struggling with deeper elements

我正在尝试解析一个相当嵌套的 XML 文件。 我花了最后几个小时试图找到一个没有运气的解决方案。 我不确定问题是与命名空间有关,还是需要在循环中 findall 。 我能够提取更高级别的元素,但没有提取更深层的嵌套元素。 我希望将 Part_number、manufacturer_name、nam ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2023 STACKOOM.COM