在 Parquet 中使用 Dask date/timestamp 列存储
Storing with Dask date/timestamp columns in Parquet
我有一个包含两列的 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 运行 a select 并获取日期?我尝试在 Drill 中使用 SELECT CAST
,但它不会将数字转换为日期。
如果没记错的话,Drill 使用旧的非标准 INT96 time stamps, which was never supported by parquet. A parquet timestamp 本质上是一个 UNIX 时间戳,作为 int64,并且具有各种精度。 Drill 必须具有正确转换其内部格式的功能。
我不是 Drill 方面的专家,但您似乎需要先将整数除以 10 的适当次方(参见 )。这个语法可能是错误的,但可能会给你这样的想法:
SELECT TO_TIMESTAMP((mycol as FLOAT) / 1000) FROM ...;
不确定是否与您相关,但您似乎只对日期值感兴趣(忽略小时、分钟等)。如果是这样,您可以使用 .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')
时间转换,可以使用.astype
或dd.to_datetime
,参见. There is also a very similar and 的答案,这表明确保时间戳向下转换为ms
解决了问题。
因此,仔细研究您提供的值可能会发现核心问题是变量缩放不匹配:
# both yield: Timestamp('2019-01-01 00:00:00')
pd.to_datetime(1546300800000000*1000, unit='ns')
pd.to_datetime(1546300800000000/1000000, unit='s')
这是关于 TO_TIMESTAMP()
函数的 Drill 文档的 link。 (https://drill.apache.org/docs/data-type-conversion/#to_timestamp)我认为@mdurant 的方法是正确的。
我会尝试:
SELECT TO_TIMESTAMP(<date_col>) FROM ...
或
SELECT TO_TIMSTAMP((<date_col> / 1000)) FROM ...
我有一个包含两列的 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 运行 a select 并获取日期?我尝试在 Drill 中使用 SELECT CAST
,但它不会将数字转换为日期。
如果没记错的话,Drill 使用旧的非标准 INT96 time stamps, which was never supported by parquet. A parquet timestamp 本质上是一个 UNIX 时间戳,作为 int64,并且具有各种精度。 Drill 必须具有正确转换其内部格式的功能。
我不是 Drill 方面的专家,但您似乎需要先将整数除以 10 的适当次方(参见
SELECT TO_TIMESTAMP((mycol as FLOAT) / 1000) FROM ...;
不确定是否与您相关,但您似乎只对日期值感兴趣(忽略小时、分钟等)。如果是这样,您可以使用 .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')
时间转换,可以使用.astype
或dd.to_datetime
,参见ms
解决了问题。
因此,仔细研究您提供的值可能会发现核心问题是变量缩放不匹配:
# both yield: Timestamp('2019-01-01 00:00:00')
pd.to_datetime(1546300800000000*1000, unit='ns')
pd.to_datetime(1546300800000000/1000000, unit='s')
这是关于 TO_TIMESTAMP()
函数的 Drill 文档的 link。 (https://drill.apache.org/docs/data-type-conversion/#to_timestamp)我认为@mdurant 的方法是正确的。
我会尝试:
SELECT TO_TIMESTAMP(<date_col>) FROM ...
或
SELECT TO_TIMSTAMP((<date_col> / 1000)) FROM ...