> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 与 pandas 的关键区别

> DataStore 与 pandas 的重要差异

尽管 DataStore 与 pandas 高度兼容，但两者之间仍有一些重要差异需要了解。

## 摘要表

| Aspect | pandas | DataStore |
| - | - | - |
| **执行** | 立即 | 惰性 |
| **返回类型** | DataFrame/Series | DataStore/ColumnExpr |
| **行顺序** | 保持不变 | 保持不变 (自动) ；在[性能模式](https://clickhouse.com/docs/zh/chdb/configuration/performance-mode.md)下不作保证 |
| **inplace** | 支持 | 不支持 |
| **索引** | 完整支持 | 简化 |
| **内存** | 所有数据都在内存中 | 数据保留在源端 |

***

## 1. 惰性与立即执行

### pandas (立即)

操作会立即执行：

```python theme={null}
import pandas as pd

df = pd.read_csv("data.csv")  # Loads entire file NOW
result = df[df['age'] > 25]   # Filters NOW
grouped = result.groupby('city')['salary'].mean()  # Aggregates NOW
```

### DataStore (惰性)

仅在需要结果时才会执行操作：

```python theme={null}
from chdb import datastore as pd

ds = pd.read_csv("data.csv")  # Just records the source
result = ds[ds['age'] > 25]   # Just records the filter
grouped = result.groupby('city')['salary'].mean()  # Just records

# Execution happens here:
print(grouped)        # Executes when displaying
df = grouped.to_df()  # Or when converting to pandas
```

### 为什么这很重要

惰性执行可带来：

* **查询优化**：多个操作会编译成一条 SQL 查询
* **列裁剪**：仅读取所需的列
* **过滤器下推**：过滤器会在源端生效
* **内存效率**：避免加载不需要的数据

***

## 2. 返回类型

### pandas

```python theme={null}
df['col']           # Returns pd.Series
df[['a', 'b']]      # Returns pd.DataFrame
df[df['x'] > 10]    # Returns pd.DataFrame
df.groupby('x')     # Returns DataFrameGroupBy
```

### DataStore

```python theme={null}
ds['col']           # Returns ColumnExpr (lazy)
ds[['a', 'b']]      # Returns DataStore (lazy)
ds[ds['x'] > 10]    # Returns DataStore (lazy)
ds.groupby('x')     # Returns LazyGroupBy
```

### 转换为 pandas 数据类型

```python theme={null}
# Get pandas DataFrame
df = ds.to_df()
df = ds.to_pandas()

# Get pandas Series from column
series = ds['col'].to_pandas()

# Or trigger execution
print(ds)  # Automatically converts for display
```

***

## 3. 执行触发器

DataStore 会在需要实际值时执行：

| 触发器 | 示例 | 说明 |
| - | - | - |
| `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

始终保留行顺序：

```python theme={null}
df = pd.read_csv("data.csv")
print(df.head())  # Always same order as file
```

### DataStore

对于大多数操作，**会自动保留**行顺序：

```python theme={null}
ds = pd.read_csv("data.csv")
print(ds.head())  # Matches file order

# Filter preserves order
ds_filtered = ds[ds['age'] > 25]  # Same order as pandas
```

DataStore 会在内部自动记录原始行的位置 (使用 `rowNumberInAllBlocks()`) ，以确保顺序与 pandas 保持一致。

### 何时会保留行顺序

* 文件源 (CSV、Parquet、JSON 等)
* pandas DataFrame 源
* 过滤操作
* 列选择
* 显式调用 `sort()` 或 `sort_values()` 之后
* 会确定顺序的操作 (`nlargest()`、`nsmallest()`、`head()`、`tail()`)

### 顺序何时可能发生变化

* 在 `groupby()` 聚合之后 (使用 `sort_values()` 可确保顺序一致)
* 使用某些 join type 进行 `merge()` / `join()` 之后
* 在 **性能模式** (`config.use_performance_mode()`) 下：任何操作的行顺序都无法保证。请参见[性能模式](https://clickhouse.com/docs/zh/chdb/configuration/performance-mode.md)。

***

## 5. 没有 inplace 参数

### pandas

```python theme={null}
df.drop(columns=['col'], inplace=True)  # Modifies df
df.fillna(0, inplace=True)              # Modifies df
df.rename(columns={'old': 'new'}, inplace=True)
```

### DataStore

不支持 `inplace=True`。请始终将结果赋值给变量：

```python theme={null}
ds = ds.drop(columns=['col'])           # Returns new DataStore
ds = ds.fillna(0)                       # Returns new DataStore
ds = ds.rename(columns={'old': 'new'})  # Returns new DataStore
```

### 为什么没有 inplace？

DataStore 使用不可变操作，以便实现：

* 查询构建 (惰性求值)
* 线程安全
* 更容易调试
* 更简洁的代码

***

## 6. 索引支持

### pandas

完整的索引支持：

```python theme={null}
df = df.set_index('id')
df.loc['user123']           # Label-based access
df.loc['a':'z']             # Label-based slicing
df.reset_index()
df.index.name = 'user_id'
```

### DataStore

简化了对索引的支持：

```python theme={null}
# Basic operations work
ds.loc[0:10]               # Integer position
ds.iloc[0:10]              # Same as loc for DataStore

# For pandas-style index operations, convert first
df = ds.to_df()
df = df.set_index('id')
df.loc['user123']
```

### DataStore 的数据来源很重要

* **DataFrame 来源**：保留 pandas 索引
* **File 来源**：使用简单的整数索引

***

## 7. 比较行为

### 与 pandas 对比

pandas 无法识别 DataStore 对象：

```python theme={null}
import pandas as pd
from chdb import datastore as ds

pdf = pd.DataFrame({'a': [1, 2, 3]})
dsf = ds.DataFrame({'a': [1, 2, 3]})

# This doesn't work as expected
pdf == dsf  # pandas doesn't know DataStore

# Solution: convert DataStore to pandas
pdf.equals(dsf.to_pandas())  # True
```

### 使用 equals()

```python theme={null}
# DataStore.equals() also works
dsf.equals(pdf)  # Compares with pandas DataFrame
```

***

## 8. 类型推断

### pandas

使用 numpy/pandas 数据类型：

```python theme={null}
df['col'].dtype  # int64, float64, object, datetime64, etc.
```

### DataStore

可使用 ClickHouse 类型：

```python theme={null}
ds['col'].dtype  # Int64, Float64, String, DateTime, etc.

# Types are converted when going to pandas
df = ds.to_df()
df['col'].dtype  # Now pandas type
```

### 显式类型转换

```python theme={null}
# Force specific type
ds['col'] = ds['col'].astype('int64')
```

***

## 9. 内存模型

### pandas

所有数据都存储在内存中：

```python theme={null}
df = pd.read_csv("huge.csv")  # 10GB in memory!
```

### DataStore

数据会一直保留在源端，直到需要时才使用：

```python theme={null}
ds = pd.read_csv("huge.csv")  # Just metadata
ds = ds.filter(ds['year'] == 2024)  # Still just metadata

# Only filtered result is loaded
df = ds.to_df()  # Maybe only 1GB now
```

***

## 10. 错误信息

### 不同的错误来源

* **pandas 错误**：来自 pandas 库
* **DataStore 错误**：来自 chDB 或 ClickHouse

```python theme={null}
# May see ClickHouse-style errors
# "Code: 62. DB::Exception: Syntax error..."
```

### 调试技巧

```python theme={null}
# View the SQL to debug
print(ds.to_sql())

# See execution plan
ds.explain()

# Enable debug logging
from chdb.datastore.config import config
config.enable_debug()
```

***

## 迁移清单

从 pandas 迁移时：

* [ ] 修改 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)` | 相同 (会触发执行) |
