总结表
| 项目 | pandas | DataStore |
|---|---|---|
| 执行 | 立即 (即时) | 惰性 (延迟) |
| 返回类型 | DataFrame/Series | DataStore/ColumnExpr |
| 行顺序 | 保持不变 | 保持不变 (自动) ;在性能模式下不保证 |
| inplace | 支持 | 不支持 |
| 索引 | 完整支持 | 简化 |
| 内存 | 所有数据均在内存中 | 数据保留在源端 |
1. 惰性执行 vs 立即执行
pandas (立即执行)
DataStore (惰性)
为什么这很重要
- 查询优化:多个操作可合并编译为一条 SQL 查询
- 列裁剪:只读取所需的列
- 过滤器下推:过滤器可在数据源端生效
- 内存效率:无需加载不需要的数据
2. 返回类型
pandas
DataStore
转换为 pandas 数据类型
3. 执行触发条件
| Trigger | Example | Notes |
|---|---|---|
print() / repr() | print(ds) | 显示时需要数据 |
len() | len(ds) | 需要行数 |
.columns | ds.columns | 需要列名 |
.dtypes | ds.dtypes | 需要类型信息 |
.shape | ds.shape | 需要维度信息 |
.values | ds.values | 需要实际数据 |
.index | ds.index | 需要索引 |
to_df() | ds.to_df() | 显式转换 |
| Iteration | for row in ds | 需要进行迭代 |
equals() | ds.equals(other) | 需要比较 |
保持惰性执行的操作
| 操作 | 返回值 |
|---|---|
filter() | DataStore |
select() | DataStore |
sort() | DataStore |
groupby() | LazyGroupBy |
join() | DataStore |
ds['col'] | ColumnExpr |
ds[['a', 'b']] | DataStore |
ds[condition] | DataStore |
4. 行顺序
pandas
DataStore
rowNumberInAllBlocks()) ,以确保顺序与 pandas 一致。
保留顺序的情况
- File 源 (CSV、Parquet、JSON 等)
- pandas DataFrame 源
- 过滤操作
- 列选择
- 显式调用
sort()或sort_values()之后 - 会定义顺序的操作 (
nlargest()、nsmallest()、head()、tail())
顺序可能不同的情况
- 在
groupby()聚合之后 (使用sort_values()以确保顺序一致) - 在使用某些 join 类型进行
merge()/join()之后 - 在 性能模式 (
config.use_performance_mode()) 下:任何操作的行顺序都不作保证。请参见 Performance Mode。
5. 不支持 inplace 参数
pandas
DataStore
inplace=True。请始终将结果赋值给变量:
为什么不支持 inplace?
- 查询构建 (惰性求值)
- 线程安全
- 更方便调试
- 更简洁的代码
6. 索引支持
pandas
DataStore
DataStore 来源很关键
- DataFrame 来源:保留 pandas 索引
- 文件来源:使用简单的整数索引
7. 比较行为
与 pandas 的比较
使用 equals()
8. 类型推断
pandas
DataStore
显式类型转换
9. 内存模型
pandas
DataStore
10. 错误信息
不同的错误来源
- pandas 错误:来自 pandas 库
- DataStore 错误:来自 chDB 或 ClickHouse
调试技巧
迁移清单
- 修改 import 语句
- 移除
inplace=True参数 - 在需要 pandas DataFrame 的地方显式调用
to_df() - 如果行顺序很重要,请添加排序
- 使用
to_pandas()进行对比测试 - 使用具有代表性的数据规模进行测试
快速参考
| pandas | DataStore |
|---|---|
df[condition] | 相同 (返回 DataStore) |
df.groupby() | 相同 (返回 LazyGroupBy) |
df.drop(inplace=True) | ds = ds.drop() |
df.equals(other) | ds.to_pandas().equals(other) |
df.loc['label'] | ds.to_df().loc['label'] |
print(df) | 相同 (会触发执行) |
len(df) | 相同 (会触发执行) |