我在使用pyarrow为拼花地板编写结构时遇到问题。根据数据集的大小,似乎存在间歇性故障。如果我对数据集进行子采样或超级采样,它有时会编写有效的数据集,有时则不会。我看不出有什么规律
我正在写一个列,带有模式
struct<creation_date: string,
expiration_date: string,
last_updated: string,
name_server: string,
registrar: string,
status: string>
这似乎不是一个版本控制问题——写入有时会成功,而且我已经能够成功地编写更复杂的数据类型,如结构列表
如果我取消对结构的测试,使每个属性都有自己的列,那么一切都很好——这与结构的编写方式有关
写入磁盘后,当我使用parquet-tools
检查时,我得到错误org.apache.parquet.io.ParquetDecodingException: Can not read value at {n} in block 0 in file
,其中n是引发问题的任何行。那一排没有什么特别的
当我把桌子放进蜂箱并尝试在那里探索时,我得到了一些更具启发性的东西:
Caused by: java.lang.IllegalArgumentException: Reading past RLE/BitPacking stream.
at parquet.Preconditions.checkArgument(Preconditions.java:55)
at parquet.column.values.rle.RunLengthBitPackingHybridDecoder.readNext(RunLengthBitPackingHybridDecoder.java:82)
at parquet.column.values.rle.RunLengthBitPackingHybridDecoder.readInt(RunLengthBitPackingHybridDecoder.java:64)
at parquet.column.values.dictionary.DictionaryValuesReader.readValueDictionaryId(DictionaryValuesReader.java:76)
at parquet.column.impl.ColumnReaderImpl$1.read(ColumnReaderImpl.java:166)
at parquet.column.impl.ColumnReaderImpl.readValue(ColumnReaderImpl.java:464)
... 35 more
奇怪的是,其他数据类型看起来很好——这个特定的结构有点抛出错误。以下是重现问题所需的代码:
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
import sys
# Command line argument to set how many rows in the dataset
_, n = sys.argv
n = int(n)
# Random whois data - should be a struct with the schema
# struct<creation_date: string,
# expiration_date: string,
# last_updated: string,
# name_server: string,
# registrar: string,
# status: string>
# nothing terribly interesting
df = pd.DataFrame({'whois':[
{'registrar': 'GoDaddy.com, LLC', 'creation_date': '2020-07-17T16:10:35', 'expiration_date': '2022-07-17T16:10:35', 'last_updated': None, 'name_server': 'ns59.domaincontrol.com\r', 'status': 'clientDeleteProhibited'},
{'registrar': 'Hongkong Domain Name Information Management Co., Limited', 'creation_date': '2020-07-17T10:28:36', 'expiration_date': '2021-07-17T10:28:36', 'last_updated': None, 'name_server': 'ns2.alidns.com\r', 'status': 'ok'},
{'registrar': 'GoDaddy.com, LLC', 'creation_date': '2020-07-17T04:04:06', 'expiration_date': '2021-07-17T04:04:06', 'last_updated': None, 'name_server': 'ns76.domaincontrol.com\r', 'status': 'clientDeleteProhibited'},
None
]})
# strangely, the bug only pops up for datasets of certain length
# When n is 2 or 5 it works fine, but 3 is busted.
df = pd.concat([df for _ in range(n)]).sample(frac=1)
print(df.tail())
table = pa.Table.from_pandas(df, preserve_index=False)
print(table)
# The write doesn't throw any errors
pq.write_table(table, '/tmp/tst2.pa')
# This read is the bit that throws the error - it's some random OSError
df = pd.read_parquet('/tmp/tst2.pa')
print(df)
更新
pyarrow==0.17.1
python==3.6.10
pandas=1.0.5
您的表架构具有嵌套结构。它基本上是一个名为whois的列,包含用户定义的类型,以及字段creation\u date、expiration\u date等
在
0.17.0
之前,在读取和写入拼花地板时不支持嵌套UDT(用户定义类型)。但这里已经提到了这一点:https://issues.apache.org/jira/browse/ARROW-1644如果您使用的是旧版本的arrow,考虑到您的数据框中只有一列,我建议不要使用UDT:
另一种选择是直接在pandas中展平桌子:
作为补充说明,您可能希望提供自己的模式,因为pandas和arrow正在尝试猜测列的类型,但对于空列,它们做得不好(最后更新的是默认为float或null)
所以你可以做一些类似的事情:
相关问题 更多 >
编程相关推荐