Чтение плохих CSV-файлов со значениями мусора - PullRequest
0 голосов
/ 24 декабря 2018

Я хочу прочитать CSV-файл, который имеет следующий формат, используя pandas:

    atrrth
    sfkjbgksjg
    airuqghlerig
    Name         Roll
    airuqgorqowi
    awlrkgjabgwl
    AAA          67
    BBB          55
    CCC          07

Как видите, если я использую pd.read_csv, я получаю довольно очевидную ошибку:

 ParserError: Error tokenizing data. C error: Expected 1 fields in line 4, saw 2

Но я хотел бы получить все данные в кадре данных.Использование error_bad_lines = False удалит важные вещи и оставит только значения мусора

Это два возможных имени столбца, как указано ниже:

Name : [Name , NAME , Name of student] 
Roll : [Rollno , Roll , ROLL]

Как этого добиться?

Ответы [ 3 ]

0 голосов
/ 24 декабря 2018

Если это действительно структура (а не просто пример того, какой мусор можно получить), вы можете просто использовать аргумент skiprows , чтобы указать, сколько строк следует пропустить.Другими словами, вы должны прочитать свой фрейм данных следующим образом:

import pandas as pd

df = pd.read_csv('your.csv', skiprows=3)

Помните, что skiprows может сделать гораздо больше.Проверьте документы.

0 голосов
/ 24 декабря 2018

Я хотел бы предложить небольшое изменение / упрощение для @ RahulAgarwal's answer .Вместо того, чтобы закрывать и повторно открывать файл, вы можете продолжить загрузку того же потока прямо в панды.Вместо того, чтобы записывать количество пропускаемых строк, вы можете записать строку заголовка и разделить ее вручную, чтобы предоставить имена столбцов:

with open(r'data.csv') as fp:
    names = next(line for line in fp if line.casefold().lstrip().startswith('name'))
    df = pd.read_csv(fp, names=names.strip().split())

Это имеет преимущество для файлов с большим количеством строк мусора.

Более детальная проверка может быть примерно такой:

def isheader(line):
    items = line.strip().split()
    if len(items) != 2:
        return False
    items = sorted(map(str.casefold, items))
    return items[0].startswith('name') and items[1].startswith('roll')

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

names = next(line for line in fp if isheader(line))
0 голосов
/ 24 декабря 2018

Откройте файл CSV и найдите строку, из которой начинается имя столбца:

with open(r'data.csv') as fp:
    skip = next(filter(
        lambda x: x[1].startswith(('Name','NAME')),
        enumerate(fp)
    ))[0]

Значение будет сохранено в skip параметр

import pandas as pd
df = pd.read_csv('data.csv', skiprows=skip)

Работает в Python 3.X

...