关于 alterlab-dask
alterlab-dask 是面向数据处理与科学计算的 Dask 技能,帮助将 pandas、NumPy 和自定义 Python 工作扩展到内存之外,并利用多核或多机执行。它覆盖惰性集合和动态任务等不同计算模式。
主要功能
- 01扩展 pandas 数据帧计算
- 02并行处理 NumPy 数组
- 03流式处理文本与 JSON
- 04构建带依赖的任务工作流
- 05选择线程、进程或分布式调度
适用场景
- 01处理超出内存容量的数据集
- 02并行读取和转换多个文件
- 03运行自定义并行计算任务
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ alterlab-ieu/ alterlab-academic-skills --skill alterlab-dask安装后在 Claude Code 中输入/alterlab-dask确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/arrays.mdbags.mdbest-practices.mddataframes.mdfutures.mdschedulers.md详细介绍
Dask
概述
Dask 是一个用于并行和分布式计算的 Python 库,支持三项关键能力:
- 在单台机器上执行超出内存容量的数据
- 并行处理,利用多个核心提升计算速度
- 分布式计算,支持跨多台机器处理 TB 级数据集
Dask 可从笔记本电脑(处理约 100 GiB)扩展到集群(处理约 100 TiB),同时保持熟悉的 Python API。
何时使用此技能
在以下情况下应使用此技能:
- 处理超出可用 RAM 容量的数据集
- 将 pandas 或 NumPy 操作扩展到更大的数据集
- 并行化计算以提升性能
- 高效处理多个文件(CSV、Parquet、JSON、文本日志)
- 构建带有任务依赖关系的自定义并行工作流
- 在多个核心或机器之间分发工作负载
不适用的情况
| 场景 | 改用 |
|---|---|
| 数据可放入 RAM,且目标是获得单机 DataFrame 的最高速度 | alterlab-polars |
| 在单台机器上进行十亿行的外存探索和大数据绘图,且不使用集群 | alterlab-vaex |
| 设计分块、压缩的 Zarr 存储和编解码器(而非对其进行计算) | alterlab-zarr |
版本说明
自 2025.1 起,采用查询规划的 DataFrame(以前称为 dask-expr)是唯一的 Dask DataFrame 实现,并包含在 dask 中;dask.config.set({"dataframe.query-planning": False})
已不再存在。文本列会以字符串 dtype 加载(在 Dask 中由 PyArrow 支持;在 pandas 3 中为 str),且归约操作不会静默跳过这些列:存在非数值列时,ddf.mean() 会引发 TypeError,而 ddf.groupby(...).mean() 会引发 NotImplementedError,因此请筛选列或传入 numeric_only=True。
核心能力
Dask 提供五个主要组件,分别适用于不同的用例:
1. DataFrames — 并行 Pandas 操作
用途:通过并行处理,将 pandas 操作扩展到更大的数据集。
适用情况:
- 表格数据超出可用 RAM 容量
- 需要同时处理多个 CSV/Parquet 文件
- Pandas 操作速度较慢,需要并行化
- 从 pandas 原型扩展到生产环境
参考文档:如需全面了解 Dask DataFrames,请参阅 references/dataframes.md,其中包括:
- 读取数据(单个文件、多个文件、glob 模式)
- 常见操作(筛选、groupby、连接、聚合)
- 使用
map_partitions执行自定义操作 - 性能优化技巧
- 常见模式(ETL、时间序列、多文件处理)
快速示例:
import dask.dataframe as dd
# Read multiple files as single DataFrame
ddf = dd.read_csv('data/2024-*.csv')
# Operations are lazy until compute()
filtered = ddf[ddf['value'] > 100]
result = filtered.groupby('category').mean(numeric_only=True).compute()
要点:
- 操作是惰性的(构建任务图),直到调用
.compute() - 使用
map_partitions执行高效的自定义操作 - 处理来自其他来源的结构化数据时,尽早转换为 DataFrame
2. Arrays — 并行 NumPy 操作
用途:通过分块算法,将 NumPy 的能力扩展到大于内存容量的数据集。
适用情况:
- 数组超出可用 RAM 容量
- 需要并行化 NumPy 操作
- 处理科学数据集(HDF5、Zarr、NetCDF)
- 需要并行线性代数或数组操作
参考文档:如需全面了解 Dask Arrays,请参阅 references/arrays.md,其中包括:
- 创建数组(来自 NumPy、随机数据或磁盘)
- 分块策略与优化
- 常见操作(算术、归约、线性代数)
- 使用
map_blocks执行自定义操作 - 与 HDF5、Zarr 和 XArray 集成
快速示例:
import dask.array as da
# Create large array with chunks
x = da.random.random((100000, 100000), chunks=(10000, 10000))
# Operations are lazy
y = x + 100
z = y.mean(axis=0)
# Compute result
result = z.compute()
要点:
- 分块大小至关重要(目标是每块约 100 MB)
- 操作会并行处理各个块
- 必要时重新分块,以提高操作效率
- 对于 Dask 不支持的操作,使用
map_blocks
3. Bags - 非结构化数据的并行处理
用途:使用函数式操作处理非结构化或半结构化数据(文本、JSON、日志)。
适用场景:
- 处理文本文件、日志或 JSON 记录
- 在结构化分析前进行数据清理和 ETL
- 处理不适合数组或数据框格式的 Python 对象
- 需要节省内存的流式处理
参考文档:如需全面了解 Dask Bags,请参阅 references/bags.md,其中包括:
- 读取文本和 JSON 文件
- 函数式操作(map、filter、fold、groupby)
- 转换为数据框
- 常见模式(日志分析、JSON 处理、文本处理)
- 性能注意事项
快速示例:
import dask.bag as db
import json
# Read and parse JSON files
bag = db.read_text('logs/*.json').map(json.loads)
# Filter and transform
valid = bag.filter(lambda x: x['status'] == 'valid')
processed = valid.map(lambda x: {'id': x['id'], 'value': x['value']})
# Convert to DataFrame for analysis
ddf = processed.to_dataframe()
要点:
- 用于初步数据清理,然后转换为 DataFrame/Array
- 使用
foldby代替groupby,以获得更好的性能 - 操作采用流式处理,且节省内存
- 复杂操作应转换为结构化格式(DataFrame)
4. Futures - 基于任务的并行化
用途:通过精细控制任务执行和依赖关系,构建自定义并行工作流。
适用场景:
- 构建动态且不断演进的工作流
- 需要立即执行任务(而非延迟执行)
- 计算依赖于运行时条件
- 实现自定义并行算法
- 需要有状态计算
参考文档:如需全面了解 Dask Futures,请参阅 references/futures.md,其中包括:
- 设置分布式客户端
- 提交任务并使用 futures
- 任务依赖关系和数据传输
- 高级协调(队列、锁、事件、actor)
- 常见模式(参数扫描、动态任务、迭代算法)
快速示例:
from dask.distributed import Client
client = Client() # Create local cluster
# Submit tasks (executes immediately)
def process(x):
return x ** 2
futures = client.map(process, range(100))
# Gather results
results = client.gather(futures)
client.close()
要点:
- 需要分布式客户端(即使仅在单台机器上运行)
- 提交任务后立即执行
- 预先分发大型数据,避免重复传输
- 每个任务约有 1ms 开销(不适合数百万个微小任务)
- 使用 actor 实现有状态工作流
5. Schedulers - 执行后端
用途:控制 Dask 任务的执行方式和位置(线程、进程、分布式)。
如何选择调度器:
- Threads(默认):适用于 NumPy/Pandas 操作、释放 GIL 的库,以及可从共享内存中受益的场景
- Processes:适用于纯 Python 代码、文本处理和受 GIL 限制的操作
- Synchronous:适用于使用 pdb 调试、性能分析和理解错误
- Distributed:适用于需要仪表板、多机器集群或高级功能的场景
参考文档:如需全面了解 Dask Schedulers,请参阅 references/schedulers.md,其中包括:
- 调度器的详细说明和特性
- 配置方法(全局、上下文管理器、每次计算)
- 性能注意事项和开销
- 常见模式和故障排查
- 用于获得最佳性能的线程配置
快速示例:
import dask
import dask.dataframe as dd
# Use threads for DataFrame (default, good for numeric)
ddf = dd.read_csv('data.csv')
result1 = ddf.mean(numeric_only=True).compute() # Uses threads
# Use processes for Python-heavy work
import dask.bag as db
bag = db.read_text('logs/*.txt')
result2 = bag.map(python_function).compute(scheduler='processes')
# Use synchronous for debugging
dask.config.set(scheduler='synchronous')
result3 = problematic_computation.compute() # Can use pdb
# Use distributed for monitoring and scaling
from dask.distributed import Client
client = Client()
result4 = computation.compute() # Uses distributed with dashboard
要点:
- Threads:开销最低(每个任务约 10 µs),最适合数值计算
- Processes:避免 GIL(每个任务约 10 ms),最适合 Python 任务
- Distributed:提供监控仪表板(每个任务约 1 ms),可扩展至集群
- 可以针对单次计算或全局切换调度器
最佳实践
如需全面了解性能优化、内存管理策略和常见陷阱,请参阅 references/best-practices.md。主要原则包括:
从更简单的解决方案入手
使用 Dask 前,请考虑:
- 更好的算法
- 高效的文件格式(Parquet 优于 CSV)
- 编译代码(Numba、Cython)
- 数据采样
关键性能规则
1. 不要先在本地加载数据,再交给 Dask
# Wrong: Loads all data in memory first
import pandas as pd
df = pd.read_csv('large.csv')
ddf = dd.from_pandas(df, npartitions=10)
# Correct: Let Dask handle loading
import dask.dataframe as dd
ddf = dd.read_csv('large.csv')
2. 避免重复调用 compute()
# Wrong: Each compute is separate
for item in items:
result = dask_computation(item).compute()
# Correct: Single compute for all
computations = [dask_computation(item) for item in items]
results = dask.compute(*computations)
3. 不要构建过大的任务图
- 如果任务数达到数百万,增大分块大小
- 使用
map_partitions/map_blocks合并操作 - 检查任务图大小:
len(ddf.__dask_graph__())
4. 选择合适的分块大小
- 目标:每个分块约 100 MB(或每个核心在工作节点内存中容纳 10 个分块)
- 过大:内存溢出
- 过小:调度开销过大
5. 使用仪表板
from dask.distributed import Client
client = Client()
print(client.dashboard_link) # Monitor performance, identify bottlenecks
常见工作流模式
ETL 管道
import dask.dataframe as dd
# Extract: Read data
ddf = dd.read_csv('raw_data/*.csv')
# Transform: Clean and process
ddf = ddf[ddf['status'] == 'valid']
ddf['amount'] = ddf['amount'].astype('float64')
ddf = ddf.dropna(subset=['important_col'])
# Load: Aggregate and save. Named aggregation keeps flat string column names;
# a dict-of-lists .agg() creates MultiIndex columns that Parquet rejects.
summary = ddf.groupby('category').agg(
amount_sum=('amount', 'sum'),
amount_mean=('amount', 'mean'),
)
summary.to_parquet('output/summary.parquet')
非结构化到结构化数据管道
import dask.bag as db
import json
# Start with Bag for unstructured data
bag = db.read_text('logs/*.json').map(json.loads)
bag = bag.filter(lambda x: x['status'] == 'valid')
# Convert to DataFrame for structured analysis
ddf = bag.to_dataframe()
result = ddf.groupby('category').mean(numeric_only=True).compute()
大规模数组计算
import dask.array as da
# Load or create large array
x = da.from_zarr('large_dataset.zarr')
# Process in chunks
normalized = (x - x.mean()) / x.std()
# Save result
da.to_zarr(normalized, 'normalized.zarr')
自定义并行工作流
from dask.distributed import Client
client = Client()
# Scatter large dataset once
data = client.scatter(large_dataset)
# Process in parallel with dependencies
futures = []
for param in parameters:
future = client.submit(process, data, param)
futures.append(future)
# Gather results
results = client.gather(futures)
选择合适的组件
使用此决策指南选择合适的 Dask 组件:
数据类型:
- 表格数据 → DataFrames
- 数值数组 → Arrays
- 文本/JSON/日志 → Bags(然后转换为 DataFrame)
- 自定义 Python 对象 → Bags 或 Futures
操作类型:
- 标准 pandas 操作 → DataFrames
- 标准 NumPy 操作 → Arrays
- 自定义并行任务 → Futures
- 文本处理/ETL → Bags
控制级别:
- 高级、自动化 → DataFrames/Arrays
- 低级、手动 → Futures
工作流类型:
- 静态计算图 → DataFrames/Arrays/Bags
- 动态、不断演进 → Futures
集成注意事项
文件格式
- 高效:Parquet、HDF5、Zarr(列式、压缩、适合并行处理)
- 兼容但较慢:CSV(仅用于初始导入)
- 适用于数组:HDF5、Zarr、NetCDF
集合之间的转换
# Bag → DataFrame
ddf = bag.to_dataframe()
# DataFrame → Array (for numeric data)
arr = ddf.to_dask_array(lengths=True)
# Array → DataFrame
ddf = dd.from_dask_array(arr, columns=['col1', 'col2'])
与其他库集成
- XArray:为 Dask 数组封装带标签的维度(地理空间、成像)
- Dask-ML:使用兼容 scikit-learn 的 API 进行机器学习
- Distributed:高级集群管理和监控
调试与开发
迭代式开发工作流
- 使用同步调度器在小型数据上测试:
dask.config.set(scheduler='synchronous')
result = computation.compute() # Can use pdb, easy debugging
- 使用线程在样本数据上验证:
sample = ddf.head(1000) # Small sample
# Test logic, then scale to full dataset
- 使用 distributed 扩展规模并进行监控:
from dask.distributed import Client
client = Client()
print(client.dashboard_link) # Monitor performance
result = computation.compute()
常见问题
内存错误:
- 减小分块大小
- 有策略地使用
persist(),完成后删除数据 - 检查自定义函数是否存在内存泄漏
启动缓慢:
- 任务图过大(增大分块大小)
- 使用
map_partitions或map_blocks减少任务数
并行化效果不佳:
- 分块过大(增加分区数)
- 使用线程执行 Python 代码(改用进程)
- 数据依赖阻碍并行处理
参考文件
如需详细信息,可按需阅读以下参考文档:
references/dataframes.md- 完整的 Dask DataFrame 指南references/arrays.md- 完整的 Dask Array 指南references/bags.md- 完整的 Dask Bag 指南references/futures.md- 完整的 Dask Futures 和分布式计算指南references/schedulers.md- 完整的调度器选择与配置指南references/best-practices.md- 全面的性能优化与故障排除指南
当用户需要了解此处快速指南未涵盖的特定 Dask 组件、操作或模式的详细信息时,请加载这些文件。