На главнуюКонтактыКарта сайта
В коробке инженера
В коробке инженера
Обзоры программ, интересных блогов и программирование
Заметки о Rastrwin, Matlab
  • Twitter Colee

Python3: Обработка ошибок при загрузке данных с помощью pandas

Автор: colee | Рубрика: Программы
Воскресенье, 27 ноября 2016 г.
Теги: , , Просмотров: 1056

При использовании библиотеки Pandas очень удобно загружать данные из разных источников, например из файлов с помощью функции read_csv. Все работает из коробки, много разных опций. Но если в данных, которые нужно загрузить, закралась ошибка, то тут каши не сваришь. Конечно, для анализа можно пренебречь некоторой частью данных при загрузке, то есть запустить функцию с параметром error_bad_lines=False. Тогда все строки, в которых есть ошибка, будут проигнорированы. Такой способ подходит для быстрого анализа или когда количество строк с ошибками несущественно по сравнению с размером данных. Но для точного анализа нужно загрузить все данные, то есть обработать ошибочные строки и запихнуть их в датафрейм.

Одна из возможных ошибок выглядит так

pandas.io.common.CParserError: Error tokenizing data. C error: Expected 20 fields in line 47773, saw 22

что говорит нам следующее: количество столбцов в строке не совпадает с начальным, который pandas взял за основу (по первой строке).

Мне очень понравилось решение, которое я нашел на сайте stackoverflow.com

Смысл его в том, что каждую ошибку, на которой спотыкается pandas, ловим через Exception, обрабатываем и записываем строку, на которой произошел сбой. После отработки pandas всего файла, берутся все строки с ошибками и обрабатываются по своему желанию.

В данной реализации хорошо, что, во-первых, делается максимум работы с помощью встроенной функции read_csv, во-вторых, можно настроить парсинг на определенные ошибки, в-третьих, можно впихнуть свою функцию для парсинга данных.

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

Не стоит забывать, что в python3 нет нормального решения для чтения из файла определенной строки, поэтому сделано все по-простому через открытие файла и чтение строки через функцию readline

# python3 extended function to read csv in Pandas
def pandasReadCsvExtended(files,sep=',', func_parser='', func_afterparser = ''):
    dataRez = pd.DataFrame()
    for file in files:
        line = []
        dataFile = pd.DataFrame()
        cont = True
        while cont == True:
            try:
                dataFile = pd.read_csv(file, sep=sep, skiprows=line)
                cont = False
            except Exception as e:
                errormsg = e.args[0]
                errortype = errormsg.split('.')[0].strip()
                if errortype == 'Error tokenizing data':
                    cerror = errormsg.split(':')[1].strip().replace(',', '')
                    nums = [n for n in cerror.split(' ') if str.isdigit(n)]
                    line.append(int(nums[1]) - 1)
                else:
                    print('Unknown Error: {}'.format(errormsg))
        if line != [] and callable(func_parser):
            fileIO = open(file, 'r')
            toDataFrame = []
            ln_prev = 0
            # count of columns in dataFrame
            header_count = dataFile.shape[1]
            for ln in line:
                lineSteps = ln - ln_prev
                tmp = ln_prev
                for i in range(lineSteps):
                    tmp += 1
                    fileIO.readline()
                parts = func_parser(fileIO.readline().rstrip(), header_count)
                toDataFrame.append(parts)
                ln_prev = tmp + 1
            dataErrors = pd.DataFrame.from_records(toDataFrame, columns=dataFile.columns.values.tolist())
            dataFile = pd.concat([dataFile, dataErrors], ignore_index=True)
        if callable(func_afterparser):
            func_afterparser(dataFile, file)
        dataRez = pd.concat([dataRez, dataFile], ignore_index=True)
    return dataRez


Поделиться с друзьями:
twitter.com facebook.com vkontakte.ru odnoklassniki.ru mail.ru ya.ru digg.com blogger.com livejournal.ru google.com yandex.ru del.icio.us
Оставьте комментарий!

Используйте нормальные имена

Ваш E-mail не публикуется, используется для обратной связи и для выбора аватара с сайта gravatar.com

Публикуется вместе с комментарием

усмешка LOL сыр улыбка подмигнуть ухмылка глаза в сторону в тупике удивление большое удивление малинка пустое лицо сдвинутая бровь Оо гррр ох ох неудачник смущенный больной Тау хммм бешенный злой клевый поцелуй шок крутой недовольный

Запрещается оскорблять окружающих и использовать ненормативную лексику

Вы должны включить JavaScript, чтобы оставить сообщение