我使用pyarrow来创建和分析具有生物信息的镶嵌板表格,我需要存储一些元数据,例如数据来自哪个样本,它是如何获得和处理的。
Parquet似乎支持file-wide metadata,但我找不到如何通过pyarrow编写它。我能找到的最接近的是how to write row-group metadata,但这似乎有点过分了,因为我的元数据对于文件中的所有行组都是相同的。
有没有办法用pyarrow编写文件范围内的Parquet元数据?
发布于 2020-08-29 09:10:15
此示例说明如何使用PyArrow创建包含文件元数据和列元数据的Parquet文件。
假设您有以下CSV数据:
movie,release_year
three idiots,2009
her,2013将CSV读入PyArrow表,并使用列/文件元数据定义自定义架构:
import pyarrow.csv as pv
import pyarrow.parquet as pq
import pyarrow as pa
table = pv.read_csv('movies.csv')
my_schema = pa.schema([
pa.field("movie", "string", False, metadata={"spanish": "pelicula"}),
pa.field("release_year", "int64", True, metadata={"portuguese": "ano"})],
metadata={"great_music": "reggaeton"})使用my_schema创建一个新表,并将其写出为Parquet文件:
t2 = table.cast(my_schema)
pq.write_table(t2, 'movies.parquet')读取Parquet文件并获取文件元数据:
s = pq.read_table('movies.parquet').schema
s.metadata # => {b'great_music': b'reggaeton'}
s.metadata[b'great_music'] # => b'reggaeton'获取与release_year列关联的元数据:
parquet_file.schema.field('release_year').metadata[b'portuguese'] # => b'ano'发布于 2019-11-21 23:32:08
Pyarrow将文件范围内的元数据映射到一个名为field in the table's schema的元数据。遗憾的是,(目前)还没有关于这方面的文档。
Parquit元数据格式和Pyarrow元数据格式都将元数据表示为键/值对的集合,其中键和值都必须是字符串。这很不幸,因为如果它只是一个UTF-8编码的JSON对象,它会更灵活。此外,由于这些对象在C++实现中是std::string对象,因此它们在Python中是"b字符串“(字节)对象。
Pyarrow目前在元数据字段中存储了它自己的一些信息。它有一个内置的key b'ARROW:schema'和另一个内置的key b'pandas'。在pandas示例中,该值是一个用UTF-8编码的JSON对象。这允许命名空间。"pandas“模式可以拥有所需的任意多个字段,并且它们都在"pandas”下命名。Pyarrow使用" pandas“模式来存储有关表的索引类型以及列使用的编码类型的信息(当给定数据类型有多个可能的pandas编码时)。我不确定b'ARROW:schema'代表什么。它似乎是以某种我不认识的方式编码的,我并没有真正地使用它。我假设它的目的是记录类似于"pandas“模式的事情。
为了回答你的问题,我们需要知道的最后一件事是所有的pyarrow对象都是不可变的。因此,无法简单地将字段添加到模式中。Pyarrow确实有模式实用程序方法with_metadata,它返回模式对象的克隆,但带有您自己的元数据,但这将替换现有的元数据,并且不会追加到它。在表对象replace_schema_metadata上也有实验方法,但它也会替换,并且不会更新。因此,如果你想保留现有的元数据,你必须做更多的工作。把这些放在一起我们就得到了..。
custom_metadata = {'Sample Number': '12', 'Date Obtained': 'Tuesday'}
existing_metadata = table.schema.metadata
merged_metadata = { **custom_metadata, **existing_metadata }
fixed_table = table.replace_schema_metadata(merged_metadata)将此表另存为地块文件后,它将包括Sample Number和Date Obtained的键/值元数据字段(在文件级)。
另外,请注意replace_schema_metadata和with_metadata方法可以接受常规的python字符串(如我的示例所示)。但是,它会将这些字符串转换为"b字符串“,因此如果要访问模式中的字段,则必须使用"b字符串”。例如,如果您刚刚读入一个表,并希望获得样本编号,则必须使用table.schema.metadata[b'Sample Number'],而table.schema.metadats['Sample Number']将为您提供一个KeyError。
当您开始使用它时,您可能会意识到必须不断地将Sample Number来回映射到一个整数是一件很痛苦的事情。此外,如果您的元数据在您的应用程序中表示为一个大型嵌套对象,那么将此对象映射到字符串/字符串对的集合可能会很麻烦。此外,经常记住"b字符串“键也是一件痛苦的事情。解决方案是做与pandas模式相同的事情。首先,将元数据转换为JSON对象。然后将JSON对象转换为"b字符串“。
custom_metadata_json = {'Sample Number': 12, 'Date Obtained': 'Tuesday'}
custom_metadata_bytes = json.dumps(custom_metadata_json).encode('utf8')
existing_metadata = table.schema.metadata
merged_metadata = { **{'Record Metadata': custom_metadata_bytes}, **existing_metadata }现在,您可以使用任何标准JSON类型,以任何您想要的方式嵌套任意数量的元数据字段,所有这些字段都将被命名为单个键/值对(在本例中称为“记录元数据”)。
https://stackoverflow.com/questions/52122674
复制相似问题