【问题标题】:Storing with Dask date/timestamp columns in Parquet在 Parquet 中使用 Dask 日期/时间戳列存储
【发布时间】:2021-04-02 17:06:13
【问题描述】:

我有一个 Dask 数据框,它有两列,一个日期和一个值。

我是这样存储的:

ddf.to_parquet('/some/folder', engine='pyarrow', overwrite=True)

我希望 Dask 将日期列存储为 Parquet 中的日期,但是当我使用 Apache Drill 查询它时,我得到 16 位数字(我会说时间戳)而不是日期。例如我得到:

1546300800000000 而不是 2019-01-01

1548979200000000 而不是 2019-02-01

有没有办法告诉 Dask 将列存储为日期?如何使用 Apache Drill 运行选择并获取日期?我尝试在 Drill 中使用 SELECT CAST,但它不会将数字转换为日期。

【问题讨论】:

    标签: python dask parquet apache-drill pydrill


    【解决方案1】:

    不确定是否与您相关,但您似乎只对日期值感兴趣(忽略小时、分钟等)。如果是这样,您可以使用.dt.date 将时间戳信息显式转换为日期字符串。

    import pandas as pd
    import dask.dataframe as dd
    
    sample_dates = [
        '2019-01-01 00:01:00',
        '2019-01-02 05:04:02',
        '2019-01-02 15:04:02'
    ]
    
    df = pd.DataFrame(zip(sample_dates, range(len(sample_dates))), columns=['datestring', 'value'])
    
    ddf = dd.from_pandas(df, npartitions=2)
    
    # convert to timestamp and calculate as unix time (relative to 1970)
    ddf['unix_timestamp_seconds'] = (ddf['datestring'].astype('M8[s]') - pd.to_datetime('1970-01-01')).dt.total_seconds()
    
    # convert to timestamp format and extract dates
    ddf['datestring'] = ddf['datestring'].astype('M8[s]').dt.date
    
    ddf.to_parquet('test.parquet', engine='pyarrow', write_index=False, coerce_timestamps='ms')
    

    时间转换可以使用.astypedd.to_datetime,见this question的回答。还有一个非常相似的questionanswer,这表明确保将时间戳向下转换为ms 可以解决问题。

    因此,使用您提供的值可能会发现核心问题是变量缩放不匹配:

    # both yield: Timestamp('2019-01-01 00:00:00')
    
    pd.to_datetime(1546300800000000*1000, unit='ns')
    pd.to_datetime(1546300800000000/1000000, unit='s')
    

    【讨论】:

    • 谢谢,但输入不是字符串,而是日期,在将数据框存储在镶木地板中之前,我像这样df[dateColumn] = pd.to_datetime(df[dateColumn]) 转换列,当它存储在镶木地板中时,我仍然得到时间戳为一个 INT64。 Drill 中是否有将 INT64 转换为 DATE 的函数?
    • 另外,您可能会发现这很有用:stackoverflow.com/a/57508904/10693596
    • 如果我添加 unit='s' 我会收到错误 ValueError: unit='s' not valid with non-numerical val='2019-01-01'
    • 谢谢,您发布的链接有答案,使用coerce_timestamps='ms' 存储镶木地板,然后在 Drill 中运行选择返回格式化日期
    【解决方案2】:

    如果没记错的话,Drill 使用旧的非标准INT96 时间戳,parquet 从未支持过。 parquet timestamp 本质上是一个 UNIX 时间戳,作为 int64 格式,具有不同的精度。 Drill 必须具有正确转换其内部格式的功能。

    我不是 Drill 方面的专家,但您似乎需要先将整数除以 10 的适当幂(参见 this answer)。这个语法可能是错误的,但可能会给你一些想法:

    SELECT TO_TIMESTAMP((mycol as FLOAT) / 1000) FROM ...;
    

    【讨论】:

    • 我在钻孔中找不到一个函数来转换这个,有什么想法吗?
    • 我发表了一个想法。如果您得到确切的调用,请编辑我的答案。
    【解决方案3】:

    这里是关于 TO_TIMESTAMP() 函数的 Drill 文档的链接。 (https://drill.apache.org/docs/data-type-conversion/#to_timestamp) 我认为@mdurant 的做法是正确的。

    我会尝试:

    SELECT TO_TIMESTAMP(<date_col>) FROM ...
    

    SELECT TO_TIMSTAMP((<date_col> / 1000)) FROM ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-27
      • 1970-01-01
      • 1970-01-01
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 2017-11-01
      相关资源
      最近更新 更多