使用 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_pandas
和to_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 错误。使用fastparquet
从ns
转换为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'
。
确实如此。如果您安装了pyarrow
和fastparquet
,我认为pyarrow 优先。 Pyarrow 无法识别 times
kwarg。以上是关于使用 python 和 pandas 传输和写入 Parquet 得到时间戳错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 Python/Pandas 将多索引数据写入 excel 文件
关于在python中使用pandas模块将列表list/元组tuple写入excel中
使用 pandas 在 python 中将值写入 excel