Python - 减少大型CSV文件的导入和解析时间

时间:2014-12-06 03:07:49

标签: python performance parsing csv out-of-memory

我的第一篇文章:

在开始之前,我应该注意到我对OOP相对较新,虽然我已经在SAS,R等中完成了DB / stat工作,所以我的问题可能不太好:如果我需要澄清,请告诉我任何东西。

我的问题:

我正在尝试导入和解析大型CSV文件(大约6MM行和更大的行)。我反复遇到的两个限制是运行时和内存(Python的32位实现)。下面是我的新手(第n次)在合理时间内导入和解析的简化版本。 如何加快此过程?由于内存限制和使用pandas进行汇总,我在导入和执行临时摘要时拆分文件:

解析和总结:

def ParseInts(inString):
    try:
        return int(inString)
    except:
        return None
def TextToYearMo(inString):
    try:
        return 100*inString[0:4]+int(inString[5:7])
    except:
        return 100*inString[0:4]+int(inString[5:6])
def ParseAllElements(elmValue,elmPos):
    if elmPos in [0,2,5]:
        return elmValue
    elif elmPos == 3:
        return TextToYearMo(elmValue)
    else:
        if elmPos == 18:
            return ParseInts(elmValue.strip('\n'))
        else:
            return ParseInts(elmValue)

def MakeAndSumList(inList):
    df = pd.DataFrame(inList, columns = ['x1','x2','x3','x4','x5',
                                         'x6','x7','x8','x9','x10',
                                         'x11','x12','x13','x14'])
    return df[['x1','x2','x3','x4','x5',
               'x6','x7','x8','x9','x10',
               'x11','x12','x13','x14']].groupby(
               ['x1','x2','x3','x4','x5']).sum().reset_index()

函数调用:

def ParsedSummary(longString,delimtr,rowNum):
    keepColumns = [0,3,2,5,10,9,11,12,13,14,15,16,17,18]

    #Do some other stuff that takes very little time

    return [pse.ParseAllElements(longString.split(delimtr)[i],i) for i in keepColumns]

def CSVToList(fileName, delimtr=','):
    with open(fileName) as f:
        enumFile = enumerate(f)
        listEnumFile = set(enumFile)
        for lineCount, l in enumFile:
            pass

        maxSplit = math.floor(lineCount / 10) + 1

        counter = 0
        Summary = pd.DataFrame({}, columns = ['x1','x2','x3','x4','x5',
                                              'x6','x7','x8','x9','x10',
                                              'x11','x12','x13','x14'])
        for counter in range(0,10):
            startRow     = int(counter * maxSplit)
            endRow       = int((counter + 1) * maxSplit)
            includedRows = set(range(startRow,endRow))

            listOfRows = [ParsedSummary(row,delimtr,rownum) 
                            for rownum, row in listEnumFile if rownum in includedRows]
            Summary = pd.concat([Summary,pse.MakeAndSumList(listOfRows)])

            listOfRows = []
            counter += 1
    return Summary

(同样,这是我的第一个问题 - 所以如果我简化太多,或者更有可能,太少,我会道歉,但我不知道如何加快这一点。)

对于运行时比较:

使用Access我可以在< 5分钟内导入,解析,汇总和合并这个大小范围内的几个文件(尽管我的2GB lim是正确的)。我希望我能在Python中获得可比较的结果 - 目前我估计一个文件的运行时间约为30分钟。注意:我在Access'悲惨的环境中扔了一些东西只是因为我没有随时可以安装的管理员权限。

编辑:更新的解析代码。通过改变一些条件逻辑来尝试/除去,能够减少五分钟(在25米的运行时间)。此外 - 运行时估计不包括熊猫部分 - 我忘了我在测试时评论过,但它的影响似乎可以忽略不计。

1 个答案:

答案 0 :(得分:1)

如果您想优化性能,请不要在Python中使用自己的CSV阅读器。已经有一个标准的csv模块。也许pandasnumpy有更快的csv读者;我不确定。

来自https://softwarerecs.stackexchange.com/questions/7463/fastest-python-library-to-read-a-csv-file

  

简而言之,pandas.io.parsers.read_csv击败其他所有人,NumPy的loadtxt速度非常慢,NumPy from_fileload的速度非常快。