Решение
converters = {'Datum': lambda x: pd.to_datetime(x, format='%d.%m.%Y')}
df1 = pd.read_csv('german_csv_test.csv', sep=';', thousands='.', decimal=',', encoding='latin1',
converters=converters, index_col='Datum')
Немецкие CSV-файлы сложны, потому что на первый взгляд они выглядят нормально, но все типы данных неверны, и переключение между месяцем и днем может расстраивать. Вышеуказанные параметры работают с широким спектром европейских файлов csv. Далее я объясню каждый параметр.
Параметр sep=';'
Почти во всех немецких CSV-файлах используется точка с запятой ';' как характер разделения. Это справедливо для большинства европейских стран. Вы можете возразить, что это неправильно, потому что csv означает «значения, разделенные запятыми». Но дело не в правильном или неправильном, а в условности. И вы могли бы сказать, что csv означает «значения, разделенные символами» .
Параметры thousands='.'
и decimal=','
Кроме того, большинство европейских стран используют точку для группировки тысячи и запятая для разделения десятичных знаков. Эта замечательная статья объясняет, почему.
Параметр encoding='latin1'
Если вы посмотрите немецкую кодировку в Python документации , вы увидите код c 'cp273' для немецкого языка. Используется редко. Вам должно быть хорошо с "latin1" для Западной Европы. Использование этого кода c извлекает выгоду из внутренней оптимизации в CPython:
CPython детали реализации : Некоторые распространенные кодировки могут обходить кодеки поисковый механизм для повышения производительности. Эти возможности оптимизации распознаются CPython только для ограниченного набора псевдонимов (без учета регистра): utf-8, utf8, latin-1, latin1, iso-8859-1, iso8859-1, mbcs (Windows только), ascii, us-ascii, utf-16, utf16, utf-32, utf32 и то же самое с использованием подчеркивания вместо тире. Использование альтернативных псевдонимов для этих кодировок может привести к более медленному выполнению.
Для дальнейшего чтения посмотрите этот пост SO и блог Джоэла Спольски .
Параметр converters=converters
Конвертеры недооцениваются большинством pandas пользователей. Это похоже на сложное решение простой проблемы. Почему бы не использовать pd.to_datetime()
после прочтения файла? Вы хотите отделить ввод от обработки данных (см. модель IPO ).
Я видел (и писал) что-то подобное много раз:
df = pd.read_csv('test.csv')
df['Revenue'] = df['Price'] * df['Quantity'] # I don't have to clean up all columns. I just need the revenue.
(...) # Some other code
# Plotting revenue
df['Revenue'] = df['Revenue'] / 1000
df['Date'] = pd.to_datetime(df['Date']) # Oh, the dates are still strings. I can fix this easily before plotting.
В следующей итерации вы можете переместить pd.to_datetime()
вверх. А может и нет. И, вероятно, это приводит к какому-то неожиданному поведению. Через два месяца после того, как вы написали такой код, вы просто видите длинную последовательность неструктурированных pandas операций и думаете: « Это беспорядок. »
Есть несколько способов очистить ваш фрейм данных. Но почему бы не использовать встроенные преобразователи? Если вы определяете dtypes
и converters
для каждого столбца вашего фрейма данных, вам не нужно оглядываться назад (в гневе). Вы стоите на твердой почве после звонка pd.read_csv()
.
Имейте в виду, что конвертеры принимают только функции. Вот почему я использовал в конвертере лямбда-функцию. В противном случае я не смог бы указать параметр формата.
Подробнее о преобразователях см. В документации и в этом сообщении SO
Параметр index_col='Datum'
Это просто определяет столбец индекса. Это удобно, потому что альтернатива df = df.set_index('Datum')
не так хороша. Кроме того, это помогает, как и конвертеры, отделять входной блок от обработки данных.