Чтение нескольких CSV-файлов в Pandas по частям

Как импортировать и читать несколько CSV-файлов по частям, когда у нас есть несколько CSV-файлов, а общий размер всех CSV-файлов составляет около 20 ГБ?

Я не хочу использовать Spark, так как хочу использовать модель в SkLearn, поэтому мне нужно решение в самом Pandas.

Мой код:

allFiles = glob.glob(os.path.join(path, "*.csv"))
df = pd.concat((pd.read_csv(f,sep=",") for f in allFiles))
df.reset_index(drop=True, inplace=True)

Но это не удается, так как общий размер всех CSV на моем пути составляет 17 ГБ.

Я хочу читать его по частям, но получаю ошибку, если пытаюсь так:

  allFiles = glob.glob(os.path.join(path, "*.csv"))
  df = pd.concat((pd.read_csv(f,sep=",",chunksize=10000) for f in allFiles))
  df.reset_index(drop=True, inplace=True)

Ошибка, которую я получаю, заключается в следующем:

"невозможно объединить объект типа ""; допустимы только объекты pd.Series, pd.DataFrame и pd.Panel (устаревшие)"

Кто-нибудь может помочь?


person pythonNinja    schedule 04.03.2019    source источник
comment
Вы пробовали df = pd.concat([pd.read_csv(f,sep=",",chunksize=10000) for f in allFiles]). т.е. с квадратными скобками? Я думаю, что обычные кронштейны дают вам генератор ...   -  person mortysporty    schedule 04.03.2019
comment
@mortysporty нет, не помогло. Та же ошибка   -  person pythonNinja    schedule 04.03.2019
comment
Глядя на документацию для pd.read_csv, похоже, что указание аргумента chunksize заставляет вызов метода возвращать объект TextFileReader (а не кадр данных), который необходимо повторить.   -  person mortysporty    schedule 04.03.2019
comment
Если у вас нет необходимой оперативной памяти для хранения результатов всех фрагментов, то не имеет значения, читаете ли вы их по частям или нет... вы все равно заставите свою машину гудеть...   -  person Jon Clements♦    schedule 04.03.2019
comment
@JonClements - у меня есть оперативная память. Просто она делает процесс чтения очень медленным и снижает производительность.   -  person pythonNinja    schedule 04.03.2019
comment
Можете ли вы предоставить свои требования к оборудованию? Насколько велика ваша оперативная память? Сколько у вас CPU/GPU?   -  person smerllo    schedule 09.02.2020


Ответы (3)


чтобы прочитать большой файл csv, вы можете использовать chunksize, но в этом случае вам нужно использовать итератор следующим образом:

for df in pd.read_csv('file.csv', sep=',', iterator=True, chunksize=10000):
    process(df)

вам нужно объединить или добавить каждый фрагмент

или вы могли бы сделать это:

df = pd.read_csv('file.csv',, sep=',', iterator=True, chunksize=10000)
for chunk in df:
    process(chunk)

для чтения нескольких файлов: например

listfile = ['file1,'file2]
dfx = pd.DataFrame()
def process(d):
    #dfx=dfx.append(d) or dfx = pd.concat(dfx, d)
    #other coding

for f in listfile:
    for df in pd.read_csv(f, sep=',', iterator=True, chunksize=10000):
        process(df)

после того, как у вас будет много файлов, вы можете использовать DASK или пул из многопроцессорной библиотеки, чтобы запустить много процессов чтения

В любом случае, либо у вас достаточно памяти, либо вы теряете время

person Frenchy    schedule 04.03.2019
comment
это отлично работает, если я пытаюсь прочитать 1 csv. Но в моем случае у меня есть куча csv в моей папке. Итак, read_csv (file.csv) использует здесь только 1 файл, но у меня есть папка с большим количеством файлов csv. Я поэтому объединяю их в моем примере кода - person pythonNinja; 04.03.2019
comment
@pythonNinja я предлагаю вам удалить максимум данных, неиспользуемых для вашего машинного обучения ... я изменил свою программу для чтения нескольких файлов ... - person Frenchy; 04.03.2019
comment
спасибо, но в тот момент, когда я пытаюсь объединить данные, я получаю ту же ошибку - person pythonNinja; 05.03.2019

Это интересный вопрос. Я не пробовал это, но я думаю, что код будет выглядеть примерно так, как показано ниже.

import pandas as pd
import csv
import glob
import os

#os.chdir("C:\\your_path\\")
results = pd.DataFrame([])
filelist = glob.glob("C:\\your_path\\*.csv")
#dfList=[]
for filename in filelist:
    print(filename)  
    namedf = pd.read_csv(filename, skiprows=0, index_col=0)
    results = results.append(namedf)

results.to_csv('C:\\your_path\\Combinefile.csv')


chunksize = 10 ** 6
for chunk in pd.read_csv('C:\\your_path\\Combinefile.csv', chunksize=chunksize):
    process(chunk)

Возможно, вы могли бы загрузить все в память и обработать напрямую, но, вероятно, обработка всего заняла бы намного больше времени.

person ASH    schedule 11.03.2019

Один из способов сделать это — разбить фрейм данных на фрагменты с помощью pd.read_csv(file, chunksize=chunksize), а затем, если последний прочитанный фрагмент короче, чем размер фрагмента, сохранить дополнительный бит, а затем добавить его в первый файл массива. следующий кусок.

Но не забудьте прочитать меньший первый фрагмент следующего файла, чтобы он равнялся общему размеру фрагмента.

def chunk_from_files(dir, master_chunksize):
    '''
    Provided a directory, loops through files and chunks out dataframes.
    :param dir: Directory to csv files.
    :param master_chunksize: Size of chunk to output.
    :return: Dataframes with master_chunksize chunk.
    '''
    files = os.listdir(dir)

    chunksize = master_chunksize
    extra_chunk = None # Initialize the extra chunk.
    for file in files:
        csv_file = os.path.join(dir, file)

        # Alter chunksize if extra chunk is not None.
        if extra_chunk is not None:
            chunksize = master_chunksize - extra_chunk.shape[0]

        for chunk in pd.read_csv(csv_file, chunksize=chunksize):
            if extra_chunk is not None: 
                # Concatenate last small chunk of previous file with altered first chunk of next file.
                chunk = pd.concat([chunk, extra_chunk])
                extra_chunk = None
                chunksize = master_chunksize # Reset chunksize.
            elif chunk.shape[0] < chunksize:
                # If last chunk is less than chunk size, set is as the extra bit.
                extra_chunk = chunk
                break

            yield chunk
person Community    schedule 08.04.2020