熊猫数据框类型datetime64 [ns]在Hive / Athena中不起作用

时间:2018-12-25 06:06:13

标签: python pandas hive amazon-athena fastparquet

我正在开发一个python应用程序,它将csv文件转换为与蜂巢/雅典娜兼容的镶木地板格式,并且我正在使用fastparquet和pandas库执行此操作。在诸如2018-12-21 23:45:00之类的csv文件中有时间戳记值,需要在镶木文件中以timestamp类型写入。以下是我正在运行的代码,

columnNames = ["contentid","processed_time","access_time"]

dtypes = {'contentid': 'str'}

dateCols = ['access_time', 'processed_time']

s3 = boto3.client('s3')

obj = s3.get_object(Bucket=bucketname, Key=keyname)

df = pd.read_csv(io.BytesIO(obj['Body'].read()), compression='gzip', header=0, sep=',', quotechar='"', names = columnNames, error_bad_lines=False, dtype=dtypes, parse_dates=dateCols)

s3filesys = s3fs.S3FileSystem()

myopen = s3filesys.open

write('outfile.snappy.parquet', df, compression='SNAPPY', open_with=myopen,file_scheme='hive',partition_on=PARTITION_KEYS)

代码成功运行,下面是熊猫创建的数据框

contentid                 object
processed_time            datetime64[ns]
access_time               datetime64[ns]

最后,当我在Hive和athena中查询实木复合地板文件时,时间戳值为+50942-11-30 14:00:00.000而不是2018-12-21 23:45:00

我们非常感谢您的帮助

5 个答案:

答案 0 :(得分:3)

我知道这个问题很旧,但是仍然很重要。

如前所述,Athena仅支持int96作为时间戳。 使用fastparquet,可以生成雅典娜格式正确的实木复合地板文件。重要的部分是times ='int96',因为它告诉fastparquet将熊猫的datetime转换为int96时间戳。

from fastparquet import write
import pandas as pd

def write_parquet():
  df = pd.read_csv('some.csv')
  write('/tmp/outfile.parquet', df, compression='GZIP', times='int96')

答案 1 :(得分:2)

我通过这种方式解决了问题。

使用to_datetime方法转换df系列

接下来用.dt accesor选择datetime64 [ns]的日期部分

示例:

df.field = pd.to_datetime(df.field)
df.field = df.field.dt.date

之后,雅典娜将识别出数据

答案 2 :(得分:0)

我面临着同样的问题,经过大量研究,现在已经解决了。

执行时

write('outfile.snappy.parquet', df, compression='SNAPPY', open_with=myopen,file_scheme='hive',partition_on=PARTITION_KEYS)

它在幕后使用fastparquet,它对DateTime使用不同的编码 比雅典娜兼容的东西。

解决方案是:卸载fastparquet并安装pyarrow

  • pip卸载fastparquet
  • pip安装pyarrow

再次运行您的代码。这次应该可以了。 :)

答案 3 :(得分:0)

问题似乎出在雅典娜身上,它似乎仅支持int96,而当您在熊猫中创建时间戳时,它就是int64

我包含字符串日期的dataframe列是“ sdate”,我首先将其转换为时间戳记

# add a new column w/ timestamp
df["ndate"] = pandas.to_datetime["sdate"]
# convert the timestamp to microseconds
df["ndate"] = pandas.to_datetime(["ndate"], unit='us')

# Then I convert my dataframe to pyarrow
table = pyarrow.Table.from_pandas(df, preserve_index=False)

# After that when writing to parquet add the coerce_timestamps and 
# use_deprecated_int96_timstamps. (Also writing to S3 directly)
OUTBUCKET="my_s3_bucket"

pyarrow.parquet.write_to_dataset(table, root_path='s3://{0}/logs'.format(OUTBUCKET), partition_cols=['date'], filesystem=s3, coerce_timestamps='us', use_deprecated_int96_timestamps=True)

答案 4 :(得分:0)

您可以尝试:

dataframe.to_parquet(file_path, compression=None, engine='pyarrow', allow_truncated_timestamps=True, use_deprecated_int96_timestamps=True)