使用 python 和 pandas 传输和写入 Parquet 得到时间戳错误

Posted

技术标签:

【中文标题】使用 python 和 pandas 传输和写入 Parquet 得到时间戳错误【英文标题】:Transfer and write Parquet with python and pandas got timestamp error 【发布时间】:2019-05-22 10:38:53 【问题描述】:

我尝试在 python 中用熊猫 concat() 两个 parquet 文件。 它可以工作,但是当我尝试将数据框写入并保存到镶木地板文件时,它会显示错误:

 ArrowInvalid: Casting from timestamp[ns] to timestamp[ms] would lose data:

我检查了文档。 pandas,写入 parquet 文件时默认使用 ms 时间戳语法。 如何在 concat 之后使用已使用的模式将镶木地板文件变白? 这是我的代码:

import pandas as pd

table1 = pd.read_parquet(path= ('path.parquet'),engine='pyarrow')
table2 = pd.read_parquet(path= ('path.parquet'),engine='pyarrow')

table = pd.concat([table1, table2], ignore_index=True) 
table.to_parquet('./file.gzip', compression='gzip')

【问题讨论】:

看来 parquet 只支持 ms 而 pandas 正在使用 ns。您是否尝试按照here 的建议使用from_pandasto_pandas @hansaplast 你好,伙计,是的,我已经尝试过医生的建议。 ,但我认为导致它无法工作的原因是我用函数编写了错误的语法。 pd.Timestamp (np.datetime64[ns]) pandas 需要公开一些选项以允许不安全的强制转换或将 int96 纳秒时间戳写入 Parquet。你能打开一个关于熊猫的问题吗? Pandas 将给予to_parquet 的大多数关键字转发给给定的引擎。这个问题尤其可以用table.to_parquet(allow_truncated_timestamps=True)解决 【参考方案1】:

至少从v0.22 开始,Pandas 已经将未知的 kwargs 转发到底层 parquet-engine。因此,使用table.to_parquet(allow_truncated_timestamps=True) 应该可以工作——我为 pandas v0.25.0 和 pyarrow 0.13.0 验证了它。更多关键词见the pyarrow docs。

【讨论】:

当我使用 read_parquet() 和 Pyarrow 引擎从 S3 加载镶木地板文件时,我将日期时间字段作为字符串。我想用日期时间列取回数据框。 只是一个更新 - 对我来说,这个选项还必须设置 coerce_timestamps ='ms'【参考方案2】:

感谢@axel 提供link to Apache Arrow documentation:

allow_truncated_timestamps(布尔型,默认为 False)– 将时间戳强制转换为特定分辨率时允许丢失数据。例如。如果 强制转换为“ms”时,微秒或纳秒数据会丢失,请不要 引发异常。

似乎在现代 Pandas 版本中,我们可以将参数传递给 ParquetWriter

以下代码对我来说正常工作(Pandas 1.1.1,PyArrow 1.0.1):

df.to_parquet(filename, use_deprecated_int96_timestamps=True)

【讨论】:

所以这对我有用,但感觉不对...有人可以指出这是不使用已弃用时间戳的正确方法:)【参考方案3】:

我认为这是一个错误,你应该按照 Wes 所说的去做。但是,如果您现在需要工作代码,我有一个解决方法。

对我有用的解决方案是将时间戳列指定为毫秒精度。如果您需要纳秒级精度,这会破坏您的数据……但如果是这种情况,这可能是您遇到的最少问题。

import pandas as pd

table1 = pd.read_parquet(path=('path1.parquet'))
table2 = pd.read_parquet(path=('path2.parquet'))

table1["Date"] = table1["Date"].astype("datetime64[ms]")
table2["Date"] = table2["Date"].astype("datetime64[ms]")

table = pd.concat([table1, table2], ignore_index=True) 
table.to_parquet('./file.gzip', compression='gzip')

【讨论】:

这个table1["Date"].astype("datetime64[ms]") 没用,还有datetime64[ns]。熊猫 0.24.2【参考方案4】:

我在使用pd.to_parquet 时遇到了类似的问题,我的最终解决方法是使用参数engine='fastparquet',但我意识到如果您需要专门使用 PyArrow,这并没有帮助。

我尝试过但没有用的东西:

@DrDeadKnee 手动转换列 .astype("datetime64[ms]") 的解决方法对我不起作用(pandas v. 0.24.2) 将 coerce_timestamps='ms' 作为 kwarg 传递给底层 parquet 操作不会改变行为。

【讨论】:

我正面临fastparquet 和由 AWS Glue 支持的 Presto 的这个问题。获取 JDBC 错误。使用fastparquetns 转换为ms 的解决方案是什么?【参考方案5】:

在将带有 datetime64[ns] 列的 dask DataFrames 写入 AWS S3 并将它们抓取到 Athena 表中时,我遇到了一个相关的数量级问题。

问题是随后的 Athena 查询将日期时间字段显示为年份 >57000 而不是 2020。我设法使用了以下修复:

df.to_parquet(path, times="int96")

将 kwarg **"times": "int96" 转发到 fastparquet.writer.write()。

我使用包 parquet-tools 检查了生成的 parquet 文件。它确实将日期时间列显示为 INT96 存储格式。在 Athena(基于 Presto)上,int96 格式得到很好的支持,并且没有数量级问题。

参考:https://github.com/dask/fastparquet/blob/master/fastparquet/writer.py,函数write(),kwarg times。 (dask 2.30.0 ; fastparquet 0.4.1 ; pandas 1.1.4)

【讨论】:

如果您有多个引擎,请确保在to_parquet 方法中也传递engine='fastparquet' 确实如此。如果您安装了pyarrowfastparquet,我认为pyarrow 优先。 Pyarrow 无法识别 times kwarg。

以上是关于使用 python 和 pandas 传输和写入 Parquet 得到时间戳错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python/Pandas 将多索引数据写入 excel 文件

python Pandas 读取数据,写入文件

关于在python中使用pandas模块将列表list/元组tuple写入excel中

使用 pandas 在 python 中将值写入 excel

使用 Pandas .to_sql 将 JSON 列写入 Postgres

如何使用 Python Pandas 将 CSV 文件写入 XLSX?