Python 使用pyarrow编写带有结构的拼花地板文件时出错 问题

Python 使用pyarrow编写带有结构的拼花地板文件时出错 问题,python,hive,parquet,pyarrow,apache-arrow,Python,Hive,Parquet,Pyarrow,Apache Arrow,我在使用pyarrow为拼花地板编写结构时遇到问题。根据数据集的大小,似乎存在间歇性故障。如果我对数据集进行子采样或超级采样,它有时会编写有效的数据集,有时则不会。我看不出有什么规律 我正在写一个列,带有模式 struct<creation_date: string, expiration_date: string, last_updated: string, name_server: string, registrar: string,

我在使用pyarrow为拼花地板编写结构时遇到问题。根据数据集的大小,似乎存在间歇性故障。如果我对数据集进行子采样或超级采样,它有时会编写有效的数据集,有时则不会。我看不出有什么规律

我正在写一个列,带有模式

struct<creation_date: string, 
     expiration_date: string, 
     last_updated: string, 
     name_server: string, 
     registrar: string, 
     status: string>
奇怪的是,其他数据类型看起来很好——这个特定的结构有点抛出错误。以下是重现问题所需的代码:

将熊猫作为pd导入
将pyarrow作为pa导入
导入pyarrow.parquet作为pq
导入系统
#命令行参数,用于设置数据集中的行数
_,n=sys.argv
n=int(n)
#随机whois数据-应为具有架构的结构
#结构
#没什么特别有趣的
df=pd.DataFrame({'whois':[
{'registrator':'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':'clientdeleteProbited',
{“注册人”:“香港域名信息管理有限公司”,“创建日期”:“2020-07-17T10:28:36”,“到期日期”:“2021-07-17T10:28:36”,“上次更新”:无,“名称服务器”:“ns2.alidns.com\r”,“状态”:“ok”},
{'registrator':'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':'clientdeleteProbited',
没有一个
]})
#奇怪的是,这个错误只会在特定长度的数据集上出现
#当n为2或5时,它工作正常,但3被破坏。
df=pd.concat([df代表范围内(n)])。样品(分形=1)
打印(df.tail())
table=pa.table.from_pandas(df,preserve_index=False)
打印(表格)
#写入操作不会抛出任何错误
pq.写入表格(表格“/tmp/tst2.pa”)
#此读取是引发错误的位-这是一些随机操作错误
df=pd.read_拼花地板('/tmp/tst2.pa')
打印(df)
更新
  • 我尝试过改变结构中的项数(例如,只有前两个子项),写入失败时会改变,但对于某些大小的数据,仍然会间歇性失败
我尝试过的事情
  • 将拼花地板版本升级到2.0
  • 禁用字典写入
  • 更改压缩设置
  • 更改某些页面文件设置
  • 使用定义模式而不是插补模式
  • 取消对结构的测试(它在本例中有效,但在我的用例中无效)
环境
  • pyarrow==0.17.1
  • python==3.6.10
  • pandas=1.0.5
问题
  • 这是错误、版本不匹配还是其他原因
  • 如果问题在我这边,我应该如何解决
  • 如果这是一个bug,我应该向谁报告?箭头开发人员?拼花地板开发者?其他人

您的表架构具有嵌套结构。它基本上是一个名为whois的列,包含用户定义的类型,以及字段creation\u date、expiration\u date等

> table.schema
whois: struct<creation_date: string, expiration_date: string, last_updated: null, name_server: string, registrar: string, status: string>
  child 0, creation_date: string
  child 1, expiration_date: string
  child 2, last_updated: null
  child 3, name_server: string
  child 4, registrar: string
  child 5, status: string
另一种选择是直接在pandas中展平桌子:

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
]})
table = pa.Table.from_pandas(df, preserve_index=False).flatten()
df = pd.read_parquet('/tmp/tst2.pa')
df = pd.read_parquet('/tmp/tst2.pa')
作为补充说明,您可能希望提供自己的模式,因为pandas和arrow正在尝试猜测列的类型,但对于空列,它们做得不好(最后更新的是默认为float或null)

所以你可以做一些类似的事情:

df = pd.DataFrame([
    {'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'},
    {}
])

table_schema = pa.schema([
    pa.field('creation_date', pa.string()),
    pa.field('expiration_date', pa.string()),
    pa.field('last_updated', pa.string()),
    pa.field('name_server', pa.string()),
    pa.field('registrar', pa.string()),
    pa.field('status', pa.string()),
    
])

table = pa.Table.from_pandas(df, preserve_index=False)
pq.write_table(table, '/tmp/tst2.pa')
df = pd.read_parquet('/tmp/tst2.pa')

谢谢你的评论。几个澄清的问题:我是否误解了(特别是在这里:它说这应该是可能的?我得到了其他复杂的数据类型(例如结构列表)要工作-这里似乎还有其他事情。还有-让我觉得这些类型不受支持不是问题的是,它有时工作-它只是对不同大小的数据集失败。实际上我已经用
0.17.1
进行了测试,它对我有效。你确定你有正确版本的arrow吗?运行
pa。__要检查的版本。\uuuu
。至于为什么它有时会工作,如果您的示例数据只包含空行,它应该会工作。我怀疑这就是正在发生的情况。我100%肯定我正在使用
0.17.1
。为了调试特定于机器的问题,我在Google CoLab中运行了我原始问题的代码,它似乎工作得很好。所以看起来这个问题是我的机器特有的。我将用不同版本的python进行实验,并从源代码处编译arrow,看看这是否能解决它。
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
]})
table = pa.Table.from_pandas(df, preserve_index=False).flatten()
df = pd.read_parquet('/tmp/tst2.pa')
df = pd.read_parquet('/tmp/tst2.pa')
> table.schema
creation_date: string
expiration_date: string
last_updated: double
name_server: string
registrar: string
status: string
df = pd.DataFrame([
    {'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'},
    {}
])

table_schema = pa.schema([
    pa.field('creation_date', pa.string()),
    pa.field('expiration_date', pa.string()),
    pa.field('last_updated', pa.string()),
    pa.field('name_server', pa.string()),
    pa.field('registrar', pa.string()),
    pa.field('status', pa.string()),
    
])

table = pa.Table.from_pandas(df, preserve_index=False)
pq.write_table(table, '/tmp/tst2.pa')
df = pd.read_parquet('/tmp/tst2.pa')