Python:合并多个压缩文件并输出到多个csv文件
Python: Combine multiple zipped files and output to multiple csv files
编辑 2:
添加一些示例行以供参考。第一行是列名。
field 1|field 2|field3|id
123|xxx|aaa|118
123|xxx|aaa|56
124|xxx|aaa|184
124|yyy|aaa|156
编辑:
开放 non-Python 解决方案(grep/awk 等都可以)
csv 文件是 pipe-delimited“|”
我需要保留 headers
我有 20 个 .gz 文件(每个 ~100MB,压缩)。每个 .gz 文件中都有一个 csv 文件,包含许多列,包括一个索引列 'id'。所有文件大约有 250 个唯一 ID。
我需要将每个唯一 ID 的所有行输出到每个 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)
更新答案
既然我已经看到了你的数据,我想你想要这个:
gunzip -c *gz | awk -F'|' '=="id"{hdr=[=10=];next} hdr{f=; print hdr > f ".csv"; hdr=""} {print > f ".csv"}'
原答案
我假设你要求 "any faster solution" 允许非 Python 解决方案,所以我建议 awk
.
我生成了 4 个 1000 行虚拟数据文件,如下所示:
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=; print > id ".csv" }'
也就是说……"Unzip all the .gz
files without deleting them and pass the results to awk
. Within awk
the field separator is the comma. The id
should be picked up from the 4th field of each line. Each line should be printed to an output file whose name is id
followed by .csv
".
您应该得到 250 个 CSV 文件...很快。
注意:如果您 运行 超出打开的文件描述符,您可能需要提高限制。尝试 运行 执行以下命令:
help ulimit
ulimit -n 500
编辑 2: 添加一些示例行以供参考。第一行是列名。
field 1|field 2|field3|id
123|xxx|aaa|118
123|xxx|aaa|56
124|xxx|aaa|184
124|yyy|aaa|156
编辑:
开放 non-Python 解决方案(grep/awk 等都可以)
csv 文件是 pipe-delimited“|”
我需要保留 headers
我有 20 个 .gz 文件(每个 ~100MB,压缩)。每个 .gz 文件中都有一个 csv 文件,包含许多列,包括一个索引列 'id'。所有文件大约有 250 个唯一 ID。
我需要将每个唯一 ID 的所有行输出到每个 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)
更新答案
既然我已经看到了你的数据,我想你想要这个:
gunzip -c *gz | awk -F'|' '=="id"{hdr=[=10=];next} hdr{f=; print hdr > f ".csv"; hdr=""} {print > f ".csv"}'
原答案
我假设你要求 "any faster solution" 允许非 Python 解决方案,所以我建议 awk
.
我生成了 4 个 1000 行虚拟数据文件,如下所示:
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=; print > id ".csv" }'
也就是说……"Unzip all the .gz
files without deleting them and pass the results to awk
. Within awk
the field separator is the comma. The id
should be picked up from the 4th field of each line. Each line should be printed to an output file whose name is id
followed by .csv
".
您应该得到 250 个 CSV 文件...很快。
注意:如果您 运行 超出打开的文件描述符,您可能需要提高限制。尝试 运行 执行以下命令:
help ulimit
ulimit -n 500