Создать DataFrame из csv файлов с разной кодировкой, указанной в первой строке файла

Рейтинг: 1Ответов: 1Опубликовано: 02.02.2023

Есть 1000 csv файлов. Они все с разными кодировками. Хочу сделать из них один DataFrame, но получаю ошибку

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x84 in position 37: invalid start byte

csv файл устроен таким образом

введите сюда описание изображения

то есть в первой строке указана кодировка, но непонятно как её передать pandas что бы он корректно считывал данные.

Пробовал так, но не работает

import pandas as pd
from pathlib import Path

data_dir = Path("data/")
df = pd.concat([pd.read_csv(f) for f in data_dir.glob("*.csv")])
print(df)

На выходе нужно получить файл csv со столбцами entity, value, string. Эти данные надо брать из этих 1000 файлов(разделитель запятая).

Ответы

▲ 4Принят

Просто делайте не однострочником, а старым добрым циклом for. В цикле считываете первую строку файла, потом передаете ее как кодировку в read_csv. Все собирайте в список. После цикла уже делайте pd.concat.

import pandas as pd
from pathlib import Path

data_dir = Path("data/")

result = []

for f in data_dir.glob("*.csv"):
    print("File:", f)
    with open(f, "rb") as file:
        # В перовой строке файла убираем пробельные символы,
        # берем текст после символа "="
        encoding = file.readline().decode().strip().partition("=")[2]  
    print("Encoding:", encoding)

    # skiprows=1 - пропускаем первую строку файла, она не должна попадать в данные
    # encoding_errors="replace" - при ошибках кодировки (не удалось декодировать указанной кодировкой) заменять символы на "?"
    # header=None - указываем, что в файле нет строки с заголовками колонок
    # on_bad_lines="warn" - выводим предупреждение, например, если в какой-то строке 4 колонки вместо 3 (а не падаем с исключением)
    result.append(pd.read_csv(f, skiprows=1, encoding=encoding, on_bad_lines="warn", encoding_errors="replace", header=None))

df = pd.concat(result)
print(df)

Upd.: Полная строка для чтения csv такая:

result.append(pd.read_csv(f, skiprows=1, encoding=encoding, encoding_errors="replace", header=None, names=list("12345")))

Добавил имена колонок - 1,2,3,4,5, чтобы по умолчанию считало, что колонок 5 (в файле test-684.csv почему-то определяет, что в одной из строк их пять, почему - пока не понял).