从 dask.Series 个列表中高效地创建 dask.array
efficiently create dask.array from a dask.Series of lists
从 dask.Series 列表创建 dask.array
的最有效方法是什么?
该系列由 500 万个列表和 300 个元素组成。
目前分为500个分区。
目前我正在尝试:
pt = [delayed(np.array)(y)
for y in
[delayed(list)(x)
for x in series.to_delayed()]]
da = delayed(dask.array.concatenate)(pt, axis=1)
da = dask.array.from_delayed(da, (vec.size.compute(), 300), dtype=float)
思路是将每个分区转换成一个numpy数组并拼接
那些一起变成了dask.array
。
不过,这段代码永远需要 运行。
只要有足够的 RAM,就可以根据这些数据按顺序非常快速地构建一个 numpy 数组。
我认为您使用 dask.delayed 的方法是正确的。然而,在系列上调用 list
可能并不理想。我会创建一个函数,将您的一个系列转换为一个 numpy 数组,然后延迟处理。
def convert_series_to_array(pandas_series): # make this as fast as you can
...
return numpy_array
L = dask_series.to_delayed()
L = [delayed(convert_series_to_array)(x) for x in L]
arrays = [da.from_delayed(x, shape=(np.nan, 300), dtype=...) for x in L]
x = da.concatenate(arrays, axis=0)
此外,关于这一行:
da = delayed(dask.array.concatenate)(pt, axis=1)
永远不要在 dask 函数上调用 delayed。他们已经很懒了。
用一些虚拟数据来看这个。基于@MRocklin 的回答(并根据我的特定用例进行更多塑造),假设您的向量实际上是整数列表而不是浮点数,并且该列表存储为字符串。我们获取系列,对其进行转换,并将其存储在一个 zarr 数组文件中。
# create dummy data
vectors = [ np.random.randint(low=0,high=100,size=300).tolist() for _ in range(1000) ]
df = pd.DataFrame()
df['vector'] = vectors
df['vector'] = df['vector'].map(lambda x:f"{x}")
df['foo'] = 'bar'
ddf = dd.from_pandas( df, npartitions=100 )
# transform series data to numpy array
def convert_series_to_array( series ): # make this as fast as you can
series_ = [ast.literal_eval( i ) for i in series]
return np.stack(series_, axis=0)
L = ddf['vector'].to_delayed()
L = [delayed(convert_series_to_array)(x) for x in L]
arrays = [da.from_delayed(x, shape=(np.nan, 300), dtype=np.int64) for x in L]
x = da.concatenate(arrays, axis=0)
# store result into a zarr array
x.compute_chunk_sizes().to_zarr( 'toy_dataset.zarr', '/home/user/Documents/', overwrite=True )
从 dask.Series 列表创建 dask.array
的最有效方法是什么?
该系列由 500 万个列表和 300 个元素组成。
目前分为500个分区。
目前我正在尝试:
pt = [delayed(np.array)(y)
for y in
[delayed(list)(x)
for x in series.to_delayed()]]
da = delayed(dask.array.concatenate)(pt, axis=1)
da = dask.array.from_delayed(da, (vec.size.compute(), 300), dtype=float)
思路是将每个分区转换成一个numpy数组并拼接
那些一起变成了dask.array
。
不过,这段代码永远需要 运行。
只要有足够的 RAM,就可以根据这些数据按顺序非常快速地构建一个 numpy 数组。
我认为您使用 dask.delayed 的方法是正确的。然而,在系列上调用 list
可能并不理想。我会创建一个函数,将您的一个系列转换为一个 numpy 数组,然后延迟处理。
def convert_series_to_array(pandas_series): # make this as fast as you can
...
return numpy_array
L = dask_series.to_delayed()
L = [delayed(convert_series_to_array)(x) for x in L]
arrays = [da.from_delayed(x, shape=(np.nan, 300), dtype=...) for x in L]
x = da.concatenate(arrays, axis=0)
此外,关于这一行:
da = delayed(dask.array.concatenate)(pt, axis=1)
永远不要在 dask 函数上调用 delayed。他们已经很懒了。
用一些虚拟数据来看这个。基于@MRocklin 的回答(并根据我的特定用例进行更多塑造),假设您的向量实际上是整数列表而不是浮点数,并且该列表存储为字符串。我们获取系列,对其进行转换,并将其存储在一个 zarr 数组文件中。
# create dummy data
vectors = [ np.random.randint(low=0,high=100,size=300).tolist() for _ in range(1000) ]
df = pd.DataFrame()
df['vector'] = vectors
df['vector'] = df['vector'].map(lambda x:f"{x}")
df['foo'] = 'bar'
ddf = dd.from_pandas( df, npartitions=100 )
# transform series data to numpy array
def convert_series_to_array( series ): # make this as fast as you can
series_ = [ast.literal_eval( i ) for i in series]
return np.stack(series_, axis=0)
L = ddf['vector'].to_delayed()
L = [delayed(convert_series_to_array)(x) for x in L]
arrays = [da.from_delayed(x, shape=(np.nan, 300), dtype=np.int64) for x in L]
x = da.concatenate(arrays, axis=0)
# store result into a zarr array
x.compute_chunk_sizes().to_zarr( 'toy_dataset.zarr', '/home/user/Documents/', overwrite=True )