2016-08-06 2 views
2

У меня есть сценарий, который принимает все файлы csv в каталоге и объединяет их бок о бок, используя внешнее соединение. Проблема в том, что мой компьютер задыхается (MemoryError), когда я пытаюсь использовать его в файлах, которые мне нужно объединить (около двух десятков файлов по 6-12 Гб каждый). Я знаю, что itertools можно использовать, чтобы сделать циклы более эффективными, но я не совсем понимаю, можно ли применить их к этой ситуации. Другая альтернатива, о которой я могу думать, - это установить mySQL, изучить основы и сделать это. Очевидно, я предпочел бы сделать это на Python, если это возможно, потому что я уже изучаю его. Решение на основе R также было бы приемлемым.Эффективное слияние для большого количества огромных файлов csv

Вот мой код:

import os 
import glob 
import pandas as pd 
os.chdir("\\path\\containing\\files") 

files = glob.glob("*.csv") 
sdf = pd.read_csv(files[0], sep=',') 

for filename in files[1:]: 
    df = pd.read_csv(filename, sep=',') 
    sdf = pd.merge(sdf, df, how='outer', on=['Factor1', 'Factor2']) 

Любые советы о том, как это сделать с файлами слишком большими для памяти моего компьютера был бы весьма признателен.

ответ

4

Использование , что по моему мнению будет отвечать вашим потребностям очень хорошо. Он также обрабатывает out-of-core queries, поэтому вам не придется сталкиваться с MemoryError.

import os 
import glob 
import pandas as pd 
os.chdir("\\path\\containing\\files") 

files = glob.glob("*.csv") 
hdf_path = 'my_concatenated_file.h5' 

with pd.HDFStore(hdf_path, mode='w', complevel=5, complib='blosc') as store: 
    # This compresses the final file by 5 using blosc. You can avoid that or 
    # change it as per your needs. 
    for filename in files: 
     store.append('table_name', pd.read_csv(filename, sep=','), index=False) 
    # Then create the indexes, if you need it 
    store.create_table_index('table_name', columns=['Factor1', 'Factor2'], optlevel=9, kind='full') 
+1

, который выбросил ряд ошибок, первый из которых был: 'строка 2885, в run_code exec (code_obj, self.user_global_ns, self.user_ns)' – Thoughtcraft

+0

going csv -> hdf5 -> csv на размер файла, Re иметь дело с займет некоторое время, да? я бы попытался пойти csv -> csv, если бы мог – Kosch

+0

Не правда. HDF5 в моих тестах, по крайней мере, в 10 раз быстрее, чем csv. Далее OP не упоминает, что вывод должен быть в csv. Для любой другой реализации потребуется довольно сложный алгоритм, включающий циклы, потому что каждый файл, с которым OP должен иметь дело, составляет 6-12 ГБ. Поэтому, если ОП не находится на суперкомпьютере, вероятность того, что у него много оперативной памяти, сложна. – Kartik

0

Существует вероятность, что dask будет хорошо подходит для вашего использования. Это может зависеть от того, что вы хотите сделать после слияния.

+0

Я собираюсь сохранить его в одном огромном цВ. – Thoughtcraft

0

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

How to read a CSV file from a stream and process each line as it is written?

+0

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

+0

вы можете делать все, что хотите, до тех пор, пока оно вписывается в память. только читайте в битах, которые вам нужны, по мере необходимости, и очищайте то, что полностью/соответствует диску. – Kosch