python:改进我阅读大型(5GB)txt文件的方式

时间:2017-01-12 11:52:20

标签: python pandas numpy io large-files

我实际上正在使用pandas.read_csv来读取带有python(点云)的大型(5GB,~97百万行X 7列)txt文件。

我需要阅读前三列(代表x,y,z坐标),并检索我的点云的边界框(格式为[x_min,y_min,z_min,x_max,y_max,z_max] )。

按照目前的情况,我的代码(见下文)需要几个小时才能完成(实际上它是从昨天开始的,但它还没有完成......)。我正在使用的机器是Intel Xeon CPU ES-1630 v3 @ 3.70GHz 3.70GHz。我正在使用python 3.6 64位。

我的代码的几个关键点......

阅读相同的函数文档,它读取使用usecols参数*导致更快的解析时间和更低的内存使用*。所以我只包括我感兴趣的cols。

我并不完全了解chunksize论证的实际用途(也许我使用错误的方法......)。正如我使用它,我想它是逐行读取文件,也许这不是最好的方法。

以下是代码,任何建议(关于除使用pandas.read_csv之外的其他方法)都会有很多相关内容。

def bounding_box(filename):
startTime = datetime.now()  # initialize counter

for row in pd.read_csv(filename, sep='\s+', header=None, chunksize=1, skiprows=1, usecols=[0, 1, 2]):
    if not 'x_min' in locals():
        x_min = row.iat[0, 0]
    if not 'y_min' in locals():
        y_min = row.iat[0, 1]
    if not 'z_min' in locals():
        z_min = row.iat[0, 2]

    if not 'x_max' in locals():
        x_max = row.iat[0, 0]
    if not 'y_max' in locals():
        y_max = row.iat[0, 1]
    if not 'z_max' in locals():
        z_max = row.iat[0, 2]

    x_min = row.iat[0, 0] if row.iat[0, 0] < x_min else x_min
    y_min = row.iat[0, 1] if row.iat[0, 1] < y_min else y_min
    z_min = row.iat[0, 2] if row.iat[0, 2] < z_min else z_min

    x_max = row.iat[0, 0] if row.iat[0, 0] > x_max else x_max
    y_max = row.iat[0, 1] if row.iat[0, 1] > y_max else y_max
    z_max = row.iat[0, 2] if row.iat[0, 2] > z_max else z_max

bbox = [x_min, y_min, z_min, x_max, y_max, z_max]
print("TIME OF PROCESSING: {}".format(datetime.now() - startTime))  # print time of execution

return bbox

2 个答案:

答案 0 :(得分:2)

由于我没有准备好测试的5GB文件,我只能猜测这两个问题会减慢你的速度:

  1. 逐行读取文件(并将每行转换为数据帧)
  2. 包含SharedPreferences的复杂逻辑和每行的元素访问
  3. 要解决这些问题,请将locals()参数增加到仍然适合内存但没有分页的大值。我想,在thounsands中大块化,或者甚至更多会很好。

    然后简化(矢量化)逻辑。您可以轻松计算块的边界框,然后更新“大”边界框(如果它不包括所有块边界)。这样的事情:

    chunksize

答案 1 :(得分:1)

如果我误解了这个问题,请纠正我。你需要计算一个“边界框” - 一个包含所有点的最小“框”?

如果为这样的坐标设置min()和max()怎么办?

xpath

然而,如果它是一个唯一的任务熊猫将是“矫枉过正”。并且更快更好地解决它逐行读取文件并进行如下检查:

//td[contains(.,'Update')]/../preceding-sibling::tr//button

这种方法具有很大的优势 - 它在处理完行后逐行读取文件,它被丢弃。所以几乎它可以处理任何长度的文件 - 甚至太字节!