Панды: конвертер времени работает изолированно, но не при чтении CSV-файла - PullRequest
3 голосов
/ 02 июля 2019

Я хочу прочитать CSV-файл и преобразовать значение последовательного времени Excel в строку YYYY-MM-DD. Файл выглядит так:

A    B    start_date
0    yes  42736
1    no   42751
2    yes  43039

Функция, которую я хочу использовать в качестве конвертера:

def convert_excel_time(excel_time):  
    return (pd.to_datetime('1900-01-01') + pd.to_timedelta(excel_time,unit='day')).strftime("%Y-%m-%d")

И я использую это так:

data = pd.read_csv("data.csv",encoding = "ISO-8859-1",
                  converters={'start_date': convert_excel_time})

При использовании функции в качестве автономной, я получаю правильный результат:

excel_time = 42736
In[1]: (pd.to_datetime('1900-01-01')+pd.to_timedelta(excel_time,unit='day')).strftime("%Y-%m-%d")
Out[1]: '2017-01-03'

Однако, если я использую функцию в качестве конвертера при чтении файла CSV, все мои даты начала будут «1900-01-01». Что я делаю не так?

1 Ответ

2 голосов
/ 02 июля 2019

По умолчанию python имеет тенденцию читать файлы как строки. Как правило, это происходит, если вы не скажете это сделать иначе. Я не особенно знаком с тем, как pandas что-то делает, но, похоже, именно это и происходит: когда pd.read_csv() читает ваш файл, он интерпретирует столбец start_date как строки.

Документация для pd.to_timedelta() гласит, что она должна хорошо читать строки. Но когда вы на самом деле тестируете метод, он, кажется, не работает в данном конкретном случае.

>>> pd.to_timedelta(44, "day")
Timedelta('44 days 00:00:00')
>>> pd.to_timedelta("44", "day")
Timedelta('0 days 00:00:00.000000')

Я подозреваю, что когда он перечисляет str в качестве допустимого аргумента, он ссылается на строковое представление TimeDelta, а не на int-as-a-str. И по какой-то причине, вместо того, чтобы выдавать ошибку, он просто возвращает нулевое значение, если дано это.

Следовательно, вам просто нужно убедиться, что вы передаете ему int вместо str. Самый простой способ сделать это - просто привести excel_time в начало функции convert_excel_time():

def convert_excel_time(excel_time):  
    excel_time = int(excel_time)
    return (pd.to_datetime('1900-01-01') + pd.to_timedelta(excel_time,unit='day')).strftime("%Y-%m-%d")

При реальном чтении данных pandas предоставляет механизм, позволяющий избежать этой проблемы: dtype kwarg для pd.read_csv() позволяет вам указать ожидаемый тип каждого столбца (при этом str предположительно является дефолт). Проблема в том, что если вы дадите converters kwarg, он будет применен вместо этого, поэтому вы должны сами обработать преобразование.

...