python:改进我读取大型(5GB)txt文件的方式
我实际上使用python(点云)读取一个大的(5GB,约9700万行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。我使用的是Python3.6 64位 我的代码的几个关键点 在阅读相同的函数文档时,会发现使用python:改进我读取大型(5GB)txt文件的方式,python,pandas,numpy,io,large-files,Python,Pandas,Numpy,Io,Large Files,我实际上使用python(点云)读取一个大的(5GB,约9700万行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。我使用的是Python3.6 64位 我的代码的几个关键点 在阅读相同的函数文档时,
usecols
parameter*会导致更快的解析时间和更低的内存使用率*。所以我只包括了我感兴趣的可乐
我没有完全意识到chunksize
参数的真正用处(可能我用错了方法…)。当我使用它时,我想它是逐行读取文件,也许这不是最好的方法
这是代码,任何建议(关于使用熊猫.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
def边界框(文件名):
startTime=datetime.now()#初始化计数器
对于pd.read_csv(文件名,sep='\s+',header=None,chunksize=1,skiprows=1,usecols=[0,1,2])中的行:
如果不是局部变量()中的“x_min”:
x_min=row.iat[0,0]
如果在locals()中不是“y_min”:
y_min=row.iat[0,1]
如果在locals()中不是“z_min”:
z_min=行iat[0,2]
如果不是局部变量()中的“x_max”:
x_max=行iat[0,0]
如果不是局部变量中的“y_max”:
y_max=行iat[0,1]
如果不是局部变量()中的“z_max”:
z_max=行iat[0,2]
如果row.iat[0,0]x_max,则x_max=row.iat[0,0],否则x_max
如果row.iat[0,1]>y_max,则y_max=row.iat[0,1]如果row.iat[0,1]>y_max,则y_max=row.iat[0,1]
如果row.iat[0,2]>z_max,则z_max=row.iat[0,2]如果row.iat[0,2]>z_max否则z_max
bbox=[x_min,y_min,z_min,x_max,y_max,z_max]
打印(“处理时间:{}.format(datetime.now()-startTime))#打印执行时间
返回bbox
如果我误解了这个问题,请纠正我。您需要计算一个“边界框”——包含所有点的最小“框”
如果对像这样的坐标做min()和max(),会怎么样
# some very easy DataFrame for demo
>>> df=pd.DataFrame({0:[1,2,3], 1:[3,4,5], 2:[3,4,1]})
>>> df
0 1 2
0 1 3 3
1 2 4 4
2 3 5 1
>>> df[0].min(), df[0].max() # Xmin, Xmax
(1, 3)
>>> df[1].min(), df[1].max() # Ymin, Ymax
(3, 5)
>>> df[2].min(), df[2].max() # Zmin, Zmax
(1, 4)
然而,如果这是唯一的任务,熊猫将是“过度杀戮”。更快速、更好的解决方案是逐行读取文件并进行如下检查:
import csv, math
c = csv.reader(open('data/1.csv', 'r'), delimiter=',')
xmin = +math.inf
xmax = -math.inf
for row in c:
x = int(row[1]) ## or another column
xmin = min(xmin, x)
xmax = max(xmax, x)
# the same code for Y and Z
print(xmin, xmax)
这种方法有很大的优势——它一行接一行地读取文件,然后将其丢弃。因此,实际上它可以处理任何长度的文件,甚至是TB 由于我没有准备好5GB的文件进行测试,我只能猜测这两个问题会使您的速度变慢:
locals()
和每行的元素访问chunksize
参数增加到一个大参数,该参数仍然可以在不分页的情况下放入内存。我想thounsands中的chunksizes甚至更多都能很好地工作
然后简化(矢量化)逻辑。您可以轻松计算块的边界框,如果“大”边界框不包含所有块边界,则可以更新该边界框。诸如此类:
import numpy as np
import pandas as pd
filename = 'test.csv'
bbox_min = np.zeros(3) + np.inf
bbox_max = np.zeros(3) - np.inf
for chunk in pd.read_csv(filename, sep='\s+', header=None, chunksize=10000, skiprows=1, usecols=[0, 1, 2]):
chunkmin = chunk.values.min(axis=0)
chunkmax = chunk.values.max(axis=0)
bbox_min = np.minimum(bbox_min, chunkmin)
bbox_max = np.maximum(bbox_max, chunkmax)
bbox = np.ravel([bbox_min, bbox_max])
我不确定CSV读取部分,但在for循环之前,将x/y/z min和max变量设置为默认值(可能为0),并在每个循环中保存6个“if”语句和6个函数调用,这不是更好吗?正如所写,您无法区分将
CSV
读取到数据帧中所花费的时间,还有计算盒子的时间。我会将这两个步骤分开,并打印一些语句,例如df.info()
between.@umbe1987,与您询问的问题分开。您还可以包含一个小的数据帧和您想要的结果吗?虽然最后一种方法对于程序使用的内存来说很好,但它不适合我的情况,因为它太慢了。需要多少时间?4min23s。还不错。谢谢你的支持+1.哇,只有13分钟!。。。不知道结果是否正确,但似乎是。。我会很快检查并接受答案,以备不时之需。很高兴听到:)你能把这些信息放大一点吗?我会尽快尝试并报告。如果可能的话,也许会更快。