与pandas read_csv()相比,有一种更有效的方式来加载具有1 000 000+行的1列?

时间:2019-06-20 12:04:25

标签: python pandas dataframe

我正在尝试在Python中导入大型文件(.tab / .txt,300多个列和1000万以上的行)。该文件以制表符分隔。这些列填充有整数值。我的目标之一是对每一列求和。但是,文件太大,无法使用pandas.read_csv()进行导入,因为它消耗了太多的RAM。 样本数据:

enter image description here

因此,我编写了以下代码以导入1列,执行该列的总和,将结果存储在数据帧(= summed_cols)中,删除该列,然后继续文件的下一个列:

x=10 ###columns I'm interested in start at col 11

#empty dataframe to fill
summed_cols=pd.DataFrame(columns=["sample","read sum"])

while x<352:
    x=x+1
    sample_col=pd.read_csv("file.txt",sep="\t",usecols=[x])
    summed_cols=summed_cols.append(pd.DataFrame({"sample":[sample_col.columns[0]],"read sum":sum(sample_col[sample_col.columns[0]])}))
    del sample_col

每列代表一个样本,“读取总和”是该列的总和。因此,此代码的输出是一个具有2列的数据帧,第一列中每行一个样本,第二列中相应的读取总和。

此代码完全可以完成我想做的事情,但是效率不高。对于这个大文件,大约需要1-2个小时才能完成计算。尤其是仅加载1列就需要花费很长时间。

我的问题:是否有一种更快的方法来仅导入此大选项卡文件的一列,并执行与上述代码相同的计算?

1 个答案:

答案 0 :(得分:3)

您可以尝试以下操作:

samples = []
sums = []

with open('file.txt','r') as f:
    for i,line in enumerate(f):
        columns = line.strip().split('\t')[10:] #from column 10 onward
        if i == 0: #supposing the sample_name is the first row of each column
            samples = columns #save sample names
            sums = [0 for s in samples] #init the sums to 0
        else:
            for n,v in enumerate(columns):
                sums[n] += float(v)

result = dict(zip(samples,sums)) #{sample_name:sum, ...}

我不确定这是否行得通,因为我不知道您输入文件的内容,但是它描述了一般过程。您只打开文件一次,遍历每一行,拆分以获取列,然后存储所需的数据。 请注意,此代码不会处理缺少的值。

可以使用numpy来改善else块:

import numpy as np
...
else:
    sums = np.add(sums, map(float,columns))