使用延迟加载将LAZ读取到Dask数据帧

时间:2017-12-06 10:09:53

标签: python dask dask-delayed laspy

动作 将多个LAZ点云文件读取到Dask DataFrame。

问题 将LAZ(压缩)解压缩到LAS(未压缩)需要大量内存。不同的文件大小和由Dask创建的多个进程会导致MemoryError

尝试

我尝试限制遵循指南的工作人员数量,但似乎没有效果。

from distributed import Client, LocalCluster
cluster = LocalCluster(n_workers=3)
client = Client(cluster)

dfs = [load(file) for file in lasfiles]
df = dd.from_delayed(dfs, meta=meta)
df = df.repartition(npartitions=len(df) // part_size)
df.to_parquet('/diskstation/geomaat/geomaat3d/raw', compression='GZIP')

问题 如何以非标准格式加载如此大量的数据?

示例

以下示例是我当前的实现。它将每5个输入文件分组,以限制最多5个并行的解压缩过程。然后重新分区并写入Parquet以进行进一步处理。对我来说,这个实现似乎完全忽略了Dask的观点。

from laspy.file import File
import numpy as np
import pandas as pd
import dask.dataframe as dd
from dask.delayed import delayed

@delayed
def load(file):
    with File(file.as_posix(), mode='r') as las_data:
        las_df = pd.DataFrame(las_data.points['point'], dtype=float)
        return las_df

meta = pd.DataFrame(np.empty(0, dtype=[('X',float),('Y',float),('Z',float),('intensity',float),('raw_classification',int)]))

lasfile_dir = Path('/data/las/')
lasfiles = sorted(list(lasfile_dir.glob('*.laz')))

part_size = 5000000

for idx, sublasfiles in enumerate([lasfiles[i:i+5] for i in range(0,len(lasfiles),5)]):
    try:
        dfs = [load(file) for file in sublasfiles]
        df = dd.from_delayed(dfs, meta=meta)
        df = df.repartition(npartitions=len(df) // part_size)
        df.to_parquet('/data/las/parquet/'+str(idx), compression='GZIP')

1 个答案:

答案 0 :(得分:1)

你的实施对我来说似乎很好。

我在这里要改变的一件事是我会避免调用len(df),这会强制计算整个数据帧(没有读取全部数据帧的方法就无法确定数据帧的长度文件)。

为了清楚起见,Dask将无法在您的load函数内并行化(它没有LAZ文件的概念),因此您的并行性将受到您拥有的文件数量的限制。