之前遇到一个百G级别的CSV表格,这种CSV实际就是个数据库!当时我还傻傻的想着用R和Python处理下文件。

写一个支持超大文件的快速列分割的的python脚本

之前遇到一个百G级别的CSV表格,这种CSV实际就是个数据库!当时我还傻傻的想着用R和Python处理下文件。 想想还有什么其他路子,后面就准备用AWK命令并行处理。因为脚本不具有通用型所以只能将脚本分解步骤进行描述。

文件是很大的,所以具体的过程是: 先构建一个包含列名的分组信息的索引,然后根据索引批量的用AWk命令去对表格进行分割。

awk 'NR==1{print$0}' test.csv | sed 's:"::g' | sed 's:,:\n:g' > id.list
head id.list
eid
3-0.0
3-1.0
3-2.0
3-3.0
4-0.0
4-1.0
4-2.0
4-3.0
5-0.0

可以看到列名的,是如上所示的,所以根据我们要求,假设我想按照3-xx,4-xx这样分类进行切割,那就需要一个对应分割组的索引。 可以通过python来建立

import os
import pandas as pd

结合之前生成的列名文件(已经将其形成一竖排的表格形式),通过pandas读取列名文件和数据库文件。

# -------
infile = "test.csv"
idlist = "id.list"
  1. 将其按照'-‘进行分割,形成多列,例如3-xx变成3和xx两列
  2. 既然就是根据’-‘之前的字符分组,就可以删掉其余列
  3. 增加一列列数的索引,因为awk就是按照列数来进行分割的
  4. 分组
  5. 计算每个分组的列数范围
id_list = pd.read_csv(idlist, sep=",")
id_list = id_list.iloc[:, 0].str.split("-", expand=True)
id_list['colnum'] = id_list.index + 2
del id_list[1]
colmin = id_list.groupby(0).min()
colmax = id_list.groupby(0).max()
id_loc = pd.merge(colmin, colmax, suffixes=("_min", "_max"), how='inner', left_index=True, right_index=True)
id_loc.head()
with open(os.path.basename(idlist) + '_output.sh', 'w') as file:
    file.write(
        "#!/bin/bash\n")
    command = '''nohup awk -v FPAT='([^,]*)|("[^"]+")' -v OFS=',' '{print$1,%s}' %s > split_0405/%s.csv & \n'''
    # command = '''awk -v FPAT="([^,]+)|(\"[^\"]+\")" -v OFS=',' '{print$1,%s}' %s > split_0405/%s.csv'''
    for i in range(0, len(id_loc)):
        col = range(id_loc.iloc[i, 0], id_loc.iloc[i, 1] + 1)
        cols = ['$' + str(x) for x in col]
        file.write(command % (",".join(cols), infile, str(id_loc.index[i])))
    file.write("wait\n")

可以简单看下结果:

head -n 3 id.list_output.sh
#!/bin/bash
nohup awk -v FPAT='([^,]*)|("[^"]+")' -v OFS=',' '{print$1,$16873,$16874,$16875,$16876,$16877}' test.csv > split_0405/100001.csv & 
nohup awk -v FPAT='([^,]*)|("[^"]+")' -v OFS=',' '{print$1,$16878,$16879,$16880,$16881,$16882}' test.csv > split_0405/100002.csv & 

好了,现在就可以愉快的用qsub或者sbatch批量的投递任务了,速度贼快,我看了下,100G的文件,分割成3000多个小文件,用了一个小时就搞定了。 非常流畅

希望我写的这个小脚本,对各位的分析有所帮助