如何使用dask快速访问数据的子集?
How to use dask to quickly access subsets of the data?
我喜欢 pandas 的主要原因之一是它很容易归入子集,例如df[df.sample.isin(['a', 'c', 'p'])]
或 df[df.age < 35]
。 dask dataframe 是否也擅长(针对)这一点?我看过的教程都侧重于整列操作。
我的具体应用是(数千个命名的 GCMS 样本)x(每个样本约 20000 个时间点)x(500 m/z 通道)x(强度),我正在寻找最快的工具来拉任意子集,例如
df[df.sample.isin([...]) & df.rt.lt(800) & df.rt.gt(600) & df.mz.isin(...)]
如果 dask 是一个不错的选择,那么我将不胜感激有关如何最好地构建它的建议。
我试过的
到目前为止我尝试的是将每个样本转换为 pandas 看起来像
的数据帧
smp rt 14 15 16 17 18
0 160602_JK_OFCmix:1 271.0 64088.0 9976.0 26848.0 23928.0 89600.0
1 160602_JK_OFCmix:1 271.1 65472.0 10880.0 28328.0 24808.0 91840.0
2 160602_JK_OFCmix:1 271.2 64528.0 10232.0 27672.0 25464.0 90624.0
3 160602_JK_OFCmix:1 271.3 63424.0 10272.0 27600.0 25064.0 90176.0
4 160602_JK_OFCmix:1 271.4 64816.0 10640.0 27592.0 24896.0 90624.0
('smp'是样品名,'rt'是保留时间,14,15,...500是m/z通道),用zlib保存到hdf,level=1 ,然后使用
制作 dask 数据框
ddf = dd.read_hdf(*.hdf5, key='/*', chunksize=100000, lock=False)
但是 df = ddf[ddf.smp.isin([...a couple of samples...]).compute()
比 ddf['57'].mean().compute()
慢 100 倍。
(注意:这是 dask.set_options(get=dask.multiprocessing.get)
)
您的 dask.dataframe 由 HDF 文件支持,因此每次您执行任何操作时,您都是从磁盘读取数据。如果您的数据不适合内存,这很好,但如果您的数据适合内存,那就太浪费了。
如果您的数据适合内存
相反,如果您的数据适合内存,那么请尝试从 Pandas 数据帧中备份您的 dask.dataframe:
# ddf = dd.from_hdf(...)
ddf = dd.from_pandas(df, npartitions=20)
我希望您会从线程或分布式调度程序中看到更好的性能:http://dask.pydata.org/en/latest/scheduler-choice.html
如果您的数据不适合内存
尝试通过指定一组要在 read_hdf
调用中读取的列来减少必须读取的字节数
df = dd.read_hdf(..., columns=['57'])
或者,更好的是,使用可让您高效加载各个列的数据存储。您可以尝试像 Feather 或 Parquet 这样的东西,尽管它们都处于早期阶段:
我怀疑如果您小心避免一次阅读所有列,您可能只使用 Pandas 而不是使用 Dask.dataframe.
我喜欢 pandas 的主要原因之一是它很容易归入子集,例如df[df.sample.isin(['a', 'c', 'p'])]
或 df[df.age < 35]
。 dask dataframe 是否也擅长(针对)这一点?我看过的教程都侧重于整列操作。
我的具体应用是(数千个命名的 GCMS 样本)x(每个样本约 20000 个时间点)x(500 m/z 通道)x(强度),我正在寻找最快的工具来拉任意子集,例如
df[df.sample.isin([...]) & df.rt.lt(800) & df.rt.gt(600) & df.mz.isin(...)]
如果 dask 是一个不错的选择,那么我将不胜感激有关如何最好地构建它的建议。
我试过的
到目前为止我尝试的是将每个样本转换为 pandas 看起来像
的数据帧 smp rt 14 15 16 17 18
0 160602_JK_OFCmix:1 271.0 64088.0 9976.0 26848.0 23928.0 89600.0
1 160602_JK_OFCmix:1 271.1 65472.0 10880.0 28328.0 24808.0 91840.0
2 160602_JK_OFCmix:1 271.2 64528.0 10232.0 27672.0 25464.0 90624.0
3 160602_JK_OFCmix:1 271.3 63424.0 10272.0 27600.0 25064.0 90176.0
4 160602_JK_OFCmix:1 271.4 64816.0 10640.0 27592.0 24896.0 90624.0
('smp'是样品名,'rt'是保留时间,14,15,...500是m/z通道),用zlib保存到hdf,level=1 ,然后使用
制作 dask 数据框ddf = dd.read_hdf(*.hdf5, key='/*', chunksize=100000, lock=False)
但是 df = ddf[ddf.smp.isin([...a couple of samples...]).compute()
比 ddf['57'].mean().compute()
慢 100 倍。
(注意:这是 dask.set_options(get=dask.multiprocessing.get)
)
您的 dask.dataframe 由 HDF 文件支持,因此每次您执行任何操作时,您都是从磁盘读取数据。如果您的数据不适合内存,这很好,但如果您的数据适合内存,那就太浪费了。
如果您的数据适合内存
相反,如果您的数据适合内存,那么请尝试从 Pandas 数据帧中备份您的 dask.dataframe:
# ddf = dd.from_hdf(...)
ddf = dd.from_pandas(df, npartitions=20)
我希望您会从线程或分布式调度程序中看到更好的性能:http://dask.pydata.org/en/latest/scheduler-choice.html
如果您的数据不适合内存
尝试通过指定一组要在 read_hdf
调用中读取的列来减少必须读取的字节数
df = dd.read_hdf(..., columns=['57'])
或者,更好的是,使用可让您高效加载各个列的数据存储。您可以尝试像 Feather 或 Parquet 这样的东西,尽管它们都处于早期阶段:
我怀疑如果您小心避免一次阅读所有列,您可能只使用 Pandas 而不是使用 Dask.dataframe.