Хотя DataStore во многом совместим с pandas, важно понимать ключевые различия.
Сводная таблица
| Aspect | pandas | DataStore |
|---|---|---|
| Выполнение | Немедленное (сразу) | Отложенное (по необходимости) |
| Возвращаемые типы | DataFrame/Series | DataStore/ColumnExpr |
| Порядок строк | Сохраняется | Сохраняется (автоматически); не гарантируется в режиме производительности |
| inplace | Поддерживается | Не поддерживается |
| Индекс | Полная поддержка | Упрощённая поддержка |
| Память | Все данные в памяти | Данные остаются в источнике |
1. Отложенное и немедленное выполнение
pandas (немедленное выполнение)
Operations выполняются сразу:
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 NOWDataStore (отложенное выполнение)
Выполнение операций откладывается до тех пор, пока не потребуются результаты:
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-запрос
- Отсечение столбцов: Считываются только необходимые столбцы
- Pushdown фильтров: Фильтры применяются на стороне источника
- Эффективное использование памяти: Загружаются только нужные данные
2. Типы возвращаемых значений
pandas
df['col'] # Returns pd.Series
df[['a', 'b']] # Returns pd.DataFrame
df[df['x'] > 10] # Returns pd.DataFrame
df.groupby('x') # Returns DataFrameGroupByDataStore
ds['col'] # Returns ColumnExpr (lazy)
ds[['a', 'b']] # Returns DataStore (lazy)
ds[ds['x'] > 10] # Returns DataStore (lazy)
ds.groupby('x') # Returns LazyGroupByПреобразование в типы pandas
# 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 display3. Триггеры выполнения
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() |
Явное преобразование |
| Итерация | 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
Порядок строк всегда сохраняется:
df = pd.read_csv("data.csv")
print(df.head()) # Always same order as fileDataStore
Порядок строк автоматически сохраняется в большинстве операций:
ds = pd.read_csv("data.csv")
print(ds.head()) # Matches file order
# Filter preserves order
ds_filtered = ds[ds['age'] > 25] # Same order as pandasDataStore автоматически отслеживает исходные позиции строк (с помощью rowNumberInAllBlocks()), чтобы порядок оставался согласованным с pandas.
Когда порядок сохраняется
- Источники на основе файлов (CSV, Parquet, JSON и т. д.)
- Источники pandas DataFrame
- Операции фильтрации
- Выбор столбцов
- После явного вызова
sort()илиsort_values() - Операции, задающие порядок (
nlargest(),nsmallest(),head(),tail())
Когда порядок может отличаться
- После агрегаций
groupby()(используйтеsort_values(), чтобы обеспечить стабильный порядок) - После
merge()/join()с некоторыми типами JOIN - В режиме производительности (
config.use_performance_mode()): порядок строк не гарантируется для любых операций. См. режим производительности.
5. Параметр inplace отсутствует
pandas
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 не поддерживается. Всегда присваивайте результат:
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
Полная поддержка индексов:
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
Упрощённая поддержка индексов:
# 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:
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()
# DataStore.equals() also works
dsf.equals(pdf) # Compares with pandas DataFrame8. Вывод типов
pandas
Используются типы numpy/pandas:
df['col'].dtype # int64, float64, object, datetime64, etc.DataStore
Может использовать типы данных ClickHouse:
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Явное приведение типов
# Force specific type
ds['col'] = ds['col'].astype('int64')9. Модель памяти
pandas
Все данные хранятся в памяти:
df = pd.read_csv("huge.csv") # 10GB in memory!DataStore
Данные остаются в источнике, пока они не понадобятся:
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 now10. Сообщения об ошибках
Различные источники ошибок
- ошибки pandas: Из библиотеки pandas
- ошибки DataStore: Из chDB или ClickHouse
# May see ClickHouse-style errors
# "Code: 62. DB::Exception: Syntax error..."Советы по отладке
# 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 - Явно добавьте
to_df()там, где требуется pandas DataFrame - Добавьте сортировку, если важен порядок строк
- Используйте
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) |
То же (запускает выполнение) |