【问题标题】:Python - Reducing Import and Parse Time for Large CSV FilesPython - 减少大型 CSV 文件的导入和解析时间
【发布时间】:2015-02-04 07:56:31
【问题描述】:

我的第一篇文章:

在开始之前,我应该注意我对 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)。我希望我能在 Python 中得到可比较的结果——目前我估计一个文件的运行时间约为 30 分钟。注意:我在 Access 糟糕的环境中扔了一些东西,只是因为我没有现成的管理员权限来安装其他任何东西。

编辑:更新解析代码。通过将一些条件逻辑更改为 try/except,能够缩短 5 分钟(预计运行时间为 25m)。另外 - 运行时估计不包括 pandas 部分 - 我忘记了我在测试时已将其注释掉,但它的影响似乎可以忽略不计。

【问题讨论】:

  • 这不是 python 选项。但是你考虑过 R 中的 data.table 包吗?
  • 我没有。这对我来说是一个停机项目——我想创建一个可执行的后处理程序。而不是处理我们的模拟输出。也就是说,不需要我们的其他预报员在他们的计算机上安装任何其他软件。出于安全原因,我们的环境非常有限。
  • Reading a huge .csv in python 的可能重复项
  • 如果我错了,请纠正我,但似乎第一个只涵盖读取 CSV(我会检查他们的方法,看看它是否能提高我的阅读时间)。第二个建议使用 csv 包进行解析,但我需要改进包似乎提供的解析时间(除非我遗漏了一些东西......)。不过,感谢您的指点。

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


【解决方案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 非常快。

【讨论】:

  • 登录时遇到问题,但我记得我在尝试此操作时使用了 parse_dates=3 - 我将不使用此功能重试,并尝试使用上述函数(导入后)进行解析。
  • 我再次尝试了这种导入方法 - parse_dates 似乎导致了问题。使用这种方法导入似乎非常快,只要我使用上面的 Text to YearMo 函数(导入后),我也可以在合理的时间内根据需要解析日期。我必须深入了解 pandas 是如何编写他们的导入函数的,以及为什么它没有其他方法似乎(如果我能理解的话)出现的内存问题,以了解我做错了什么。感谢您建议我重新使用此方法!
猜你喜欢
  • 1970-01-01
  • 2020-03-20
  • 2012-08-12
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 1970-01-01
相关资源
最近更新 更多