Разобрать CSV с датами в будущем в Parquet

Я пытаюсь прочитать CSV-файл в Pandas, а затем записать его в Parquet. Проблема в том, что в CSV есть столбец даты со значением 3000-12-31, и, очевидно, у Pandas нет способа сохранить это значение как фактическую дату. Из-за этого PyArrow не может прочитать значение даты.

Пример файла и кода для воспроизведения:

test.csv

t
3000-12-31
import pandas as pd
import pyarrow as pa
df = pd.read_csv("test.csv", parse_dates=["t"])
schema = pa.schema([pa.field("t", pa.date64())])
table = pa.Table.from_pandas(df, schema=schema)

Это дает (несколько бесполезную ошибку)

TypeError: требуется целое число (получен тип str)

Как правильно это сделать?


person Kris Harper    schedule 02.11.2020    source источник
comment
Вы не можете представить эту дату как datetime64; он слишком большой. Самое большое свидание, которое у вас может быть - pd.Timestamp.max или Timestamp('2262-04-11 23:47:16.854775807'). Таким образом, даже если вы указываете его для анализа даты, он пытается и терпит неудачу, поэтому он просто сохраняет столбец как строку. Единственный реальный вариант - сохранить его как Period, df['t'] = df['t].apply(pd.Period), но я не знаю, поддерживает ли pyarrow этот dtype.   -  person ALollz    schedule 02.11.2020
comment
Да, я пробовал это, и действительно, PyArrow, похоже, не принимает Period в качестве типа даты. Думаю, мне нужно какое-то обходное решение.   -  person Kris Harper    schedule 02.11.2020


Ответы (1)


Столбцы даты и времени Pandas (которые используют тип данных datetime64[ns]) действительно не могут хранить такие даты.

Один возможный обходной путь для преобразования строк в datetime.datetime объекты в столбце dtype объекта. И тогда pyarrow сможет принять их для создания столбца даты. Это преобразование может быть выполнено, например, с dateutil:

>>> import dateutil
>>> df['t'] = df['t'].apply(dateutil.parser.parse)
>>> df
                     t
0  3000-12-31 00:00:00

>>> table = pa.Table.from_pandas(df, schema=schema)
>>> table
pyarrow.Table
t: date64[ms]

или, если вы используете фиксированный формат, использование datetime.date.strptime, вероятно, более надежно:

>>> import datetime
>>> df['t'] = df['t'].apply(lambda s: datetime.datetime.strptime(s, "%Y-%m-%d"))
>>> table = pa.Table.from_pandas(df, schema=schema)
>>> table
pyarrow.Table
t: date64[ms]
person joris    schedule 02.11.2020
comment
Это действительно хорошо работает, спасибо. Я думаю, что единственная проблема сейчас в том, что parse (или, может быть, parse в сочетании с apply) работает довольно медленно. Я думаю, мне просто придется с этим жить. - person Kris Harper; 03.11.2020
comment
Да, ожидается, что это медленнее, чем pd.to_datetime. Альтернативой может быть использование numpy вместо pandas (np.array(["2020-01-01"]).astype("datetime64[D]") также анализирует строки). Но тогда преобразование в таблицу pyarrow немного сложнее / вручную, так как вы не можете использовать from_pandas. - person joris; 03.11.2020