Чтение плохих CSV-файлов со значениями мусора

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

    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 удалит важные вещи и оставит только мусорные значения

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

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

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

3 ответа

Решение

Откройте файл 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

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

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))

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

import pandas as pd

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

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

Другие вопросы по тегам