Python: объединение нескольких сжатых файлов и вывод в несколько CSV-файлов - PullRequest
0 голосов
/ 24 сентября 2019

Редактировать:

  • Открыть для решений, не относящихся к Python (grep / awk и т. Д. В порядке)

  • CSV-файлы разделены каналом "|"

  • Мне нужно сохранить заголовки

У меня есть 20 .gz файлов (каждый ~ 100MB,заархивированы).Внутри каждого .gz-файла находится csv-файл со многими столбцами, включая индексный столбец «id».Во всех файлах содержится около 250 уникальных идентификаторов.

Мне нужно вывести все строки для каждого уникального идентификатора в каждый файл CSV (т. Е. Должно быть создано 250 файлов CSV).

Как следуетЛучше всего это сделать?

В настоящее время я использую Python, но для создания каждого CSV требуется около 1 минуты, я хотел бы знать, если есть какое-либо более быстрое решение, пожалуйста.

output_folder = 'indiv_ids/'

# get list of files
list_of_files = [filename for filename in os.listdir() if filename.endswith(".gz")]

# get list of unique ids
for i in range(len(list_of_files)):
    df = pd.read_csv(list_of_files[i], sep='|', usecols=['id'], dtype=str, engine='c')
    id_list = df['id'].unique()

    if len(id_list) == 250:
        break

# load into a list for each id
list_df = {id:[] for id in id_list}

for filename in list_of_files:
    df = pd.read_csv(filename, sep='|', dtype=str, engine='c')

    for id in id_list:
        df_id = df[df['id'] == id]
        list_df[id].append(df_id)

for id in id_list:
    # join into one big df
    df_full = pd.concat(list_df[id], axis=0)
    df_full.to_csv(f'{output_folder}{id}.csv', sep="|", index=False)

1 Ответ

0 голосов
/ 24 сентября 2019

Я полагаю, что вы запрашиваете "любое более быстрое решение" разрешает не-Python решения, поэтому я бы предложил awk.

Я создал 4 файла из 1000 строк фиктивных данных, напримерthis:

for ((i=0;i<4;i++)) ; do
    perl -E 'for($i=0;$i<1000;$i++){say "Line $i,field2,field3,",int rand 250}' | gzip > $i.gz
done

Вот несколько первых строк одного из файлов.Четвертое поле варьируется от 0..250 и должно быть похоже на ваше id поле.

Line 0,field2,field3,81
Line 1,field2,field3,118
Line 2,field2,field3,56
Line 3,field2,field3,184
Line 4,field2,field3,156
Line 5,field2,field3,87
Line 6,field2,field3,118
Line 7,field2,field3,59
Line 8,field2,field3,119
Line 9,field2,field3,183
Line 10,field2,field3,90

Тогда вы можете обработать так:

gunzip -c *gz | awk -F, '{ id=$4; print > id ".csv" }'

То есть ... "Разархивируйте все файлы .gz, не удаляя их, и передайте результаты в awk. В awk разделитель полей - запятая. id должен быть выбран из 4-го поля каждой строкиКаждая строка должна быть напечатана в выходной файл с именем id, за которым следует .csv ".

Вы должны получить 250 CSV-файлов ... довольно быстро.

Примечание : Если у вас заканчиваются дескрипторы открытых файлов, возможно, вам придется увеличить лимит.Попробуйте выполнить следующие команды:

help ulimit
ulimit -n 500
...