Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Ключевые различия с pandas

Хотя 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 NOW

DataStore (отложенное выполнение)

Выполнение операций откладывается до тех пор, пока не потребуются результаты:

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 DataFrameGroupBy

DataStore

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 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() Явное преобразование
Итерация 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 file

DataStore

Порядок строк автоматически сохраняется в большинстве операций:

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(), чтобы обеспечить стабильный порядок)
  • После 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 DataFrame

8. Вывод типов

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 now

10. Сообщения об ошибках

Различные источники ошибок

  • ошибки 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) То же (запускает выполнение)
Navigation