March 28, 2021

Как объединить набор файлов в таблицу и избежать проблем

Рассмотрим, как считать данные из набора файлов на жестком диске и не допустить ошибку.

Решать задачу будем средствами библиотеки Pandas. Допустим, что файлы располагаются по адресу people_income/files относительно вашей рабочей директории. Тогда считать данные из папки в список датафреймов (предполагается формат xlsx) можно при помощи следующего скрипта:

import os
import pandas as pd
import time
# collecting data
data_path = 'people_income/files'
data_l=[]
names=[]
all_size = 0
sizes = []
# проверяем время считывания файлов
start_r = time.time()
for (рarent, dirs, files) in os.walk(data_path):
    for fn in files:   
        start = time.time()
        data_l.append(pd.read_excel(os.path.join(рarent,fn), dtype ='str'))    
        names.append(рarent+'/'+fn)
        sizes.append(data_l[-1].shape[0])
        all_size +=  data_l[-1].shape[0]
        end = time.time()
        print(f'время считывания файла "{рarent+"/"+fn}" составило {end-start} сек.')
        print(f'форма массива -  {data_l[-1].shape}\n')
    
end_r = time.time()
print(f'время считывания всех файлов составило {end_r-start_r} сек.')

Мы задали корневую папку поиска (data_path) для добавления в список (data_l) набора датафреймов, соответствующих каждому файлу. Также наблюдаем за временем считывания и размерами массивов для того, чтобы удостовериться в правильности своих действий.

Теперь можно осуществить конкатенацию:

# проверяем время конкатенации файлов
start = time.time()
df = data_l[0]
for it in data_l[1:]:
    df = pd.concat([it,df], ignore_index=True)
end = time.time()
print(f'время конкатенации файлов составило {end-start} сек.')

В связи с возможными ошибками при автоматическом распознавании типов (рассказывал ранее) при считывании таблиц использовался параметр dtype='str'. Соответственно, после может потребоваться явно преобразовать типы некоторых столбцов:

# например
df['зарплата'] = df['зарплата'].astype(np.float64)

В ходе объединения таблиц нас могут ожидать трудности, связанные с несовпадением полей в файлах:

# проверяем совпадение полей в файлах
set_cols = set(data_l[0].columns)
for it in data_l[1:]:
    set_cols_t = set(it.columns)
    set_cols = set_cols.union(set_cols_t)
# образцовый набор стб в data_l[0]
assert len(set_cols)==len(set(data_l[0].columns)),'количество стб не совпадает'
    

Сложности могут быть связаны не только с разным обозначением столбцов, но и наличием нескольких листов в файле. Например, требуемая информация может располагаться не на первом листе, который считывается по умолчанию функцией read_excel. Тогда может потребоваться указать параметр sheet_name.

Таким образом, будьте внимательны при считывании файлов и следите за соответствием:

  • количества записей в каждой и итоговой таблице
  • наименованиями полей в исходных и итоговой таблице

Отслеживание ошибок данного типа поможет сэкономить вам нервы и время. А с какими подводными камнями при считывании файлов сталкивались вы, делитесь в комментариях?