Я полагаю, что это может быть результатом устаревшей ошибки, но я не смог выделить источник проблемы.
Окружающая среда:
- Python 2.7
- панды 0.19.1
Проблема
Использование панд для чтения / обработки / записи данных CSV приводит к редким ошибкам в выводе.
Пример данных
csv_data = """
timestamp,outdoor temperature
2019-01-10 07:16:38.758659,17.5
2019-01-10 07:31:51.449437,16.9
2019-01-10 07:47:04.458140,17.5
2019-01-10 08:02:17.372576,17.8
2019-01-10 08:17:30.156140,18.3
2019-01-10 08:32:42.878982,19.2
2019-01-10 08:47:55.782450,19.9
2019-01-10 09:03:08.907534,21.0
2019-01-10 09:18:21.599587,21.3
2019-01-10 09:33:34.572015,21.8
2019-01-10 09:48:47.524057,22.5
2019-01-10 10:04:00.420671,23.3
2019-01-10 10:19:13.187784,24.2
2019-01-10 10:34:26.118712,24.2
2019-01-10 10:49:39.000694,24.5
2019-01-10 11:04:51.870451,25.6
2019-01-10 11:20:04.763880,26.0
2019-01-10 11:35:17.541427,26.4
2019-01-10 11:50:30.252781,27.1
"""
Пример кода
Ядро ввода-вывода и код обработки (содержит одну или две строки, которые, я не думаю, имеют отношение к проблеме, но включены для полноты)
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import datetime as dt
import pandas as pd
# Load the entire CSV
df = pd.read_csv(full_path, delimiter=',', encoding='utf-8')
# Coerce column 0 name
df.columns = [c.lower() if c == 'Timestamp' else c for c in df.columns]
column_names = list(df)
# Convert column 0 to datetime
df[column_names[0]] = pd.to_datetime(df[column_names[0]], errors='coerce', format="%Y-%m-%d %H:%M:%S.%f").astype(dt.datetime)
# Drop obs older than delta hours
cut_off = dt.datetime.now() - dt.timedelta(hours=72)
df = df[df[column_names[0]] >= cut_off]
# Add a new observation to the end of the dataframe
df = df.append({column_names[0]: dt.datetime.now(), column_names[1]: '12.3'}, ignore_index=True)
# Keep max 300 obs
df = df.tail(300)
# Replace the CSV with the revised dataframe
df.to_csv(full_path, sep=',', encoding='utf-8', index=False)
Пример вывода
Иногда будет приводить к такому выводу (который включает в себя то, что представляется частями строки эпохи POSIX, добавленной к наблюдению в столбце 1):
timestamp,outdoor temperature
2019-01-10 07:16:38.758659,17.5
2019-01-10 07:31:51.449437,16.9
2019-01-10 07:47:04.458140,17.5
2019-01-10 08:02:17.372576,17.8
2019-01-10 08:17:30.156140,18.3-01-01 00:00:00
2019-01-10 08:32:42.878982,19.2
2019-01-10 08:47:55.782450,19.9
2019-01-10 09:03:08.907534,21.0
2019-01-10 09:18:21.599587,21.3
2019-01-10 09:33:34.572015,21.8
2019-01-10 09:48:47.524057,22.5
2019-01-10 10:04:00.420671,23.3
2019-01-10 10:19:13.187784,24.2-01-01 00:00:00
2019-01-10 10:34:26.118712,24.2
2019-01-10 10:49:39.000694,24.5
2019-01-10 11:04:51.870451,25.6
2019-01-10 11:20:04.763880,26.0
2019-01-10 11:35:17.541427,26.4
2019-01-10 11:50:30.252781,27.1
Я пытался использовать .append()
и .extend()
и различные комбинации кодирования / декодирования, но я обнаружил, что эта ошибка очень противоречива и трудна для воспроизведения. Сначала я подозревал, что это может быть результатом расширенных символов Unicode или расы, но я считаю, что я исключил обе эти возможности. Если код Python не является виновником, я могу исправить библиотеку pandas (но не обновить ее до более новой версии) и должен остаться на Python 2.7.
Я хочу избежать атаки методом грубой силы, при которой я просто перебираю столбец 1 obs и отбрасываю бит зла. Любые предложения будут наиболее ценными. Заранее спасибо.
Обновление 1
Дополнительные исследования показывают, что .astype()
может время от времени расстраиваться и в сочетании с errors='coerce'
может маскировать проблему. Будет ли какая-либо добавленная стоимость с использованием какой-либо другой формы преобразования даты, например:
df[column_names[0]] = [dateutil.parser.parse(obs) for obs in df[column_names[0]]]