DataStore は pandas と高い互換性がありますが、理解しておくべき重要な違いがいくつかあります。
概要表
| 観点 | pandas | DataStore |
|---|---|---|
| 実行 | 即時実行 | 遅延実行 |
| 戻り値の型 | DataFrame/Series | DataStore/ColumnExpr |
| 行の順序 | 保持される | 自動的に保持される。パフォーマンスモード では保証されない |
| inplace | 対応 | 非対応 |
| 索引 | 完全対応 | 簡略化 |
| メモリ | すべてのデータをメモリ上に保持 | データは元の場所に保持 |
1. 遅延実行と即時実行
pandas (即時実行)
操作は即座に実行されます。
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なぜ重要か
遅延実行には、次の利点があります。
- クエリ最適化: 複数の操作が 1 つの SQL クエリにコンパイルされる
- カラムプルーニング: 必要なカラムだけが読み込まれる
- フィルタのプッシュダウン: フィルタがデータソース側で適用される
- メモリ効率: 必要のないデータは読み込まない
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 LazyGroupBypandasの型への変換
# 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() |
明示的な変換 |
| 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
行の順序は常に維持されます。
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 は、pandas と同じ順序を保てるように、元の行位置を内部で自動的に追跡します (rowNumberInAllBlocks() を使用) 。
順序が保持される場合
- ファイルソース (CSV、Parquet、JSON など)
- pandas DataFrame ソース
- フィルタ操作
- カラムの選択
sort()またはsort_values()を明示的に実行した後- 順序を定義する操作 (
nlargest(),nsmallest(),head(),tail())
順序が変わることがある場合
groupby()による集計の後 (順序を一定にしたい場合はsort_values()を使用してください)- 特定の JOIN 種別で
merge()/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()) # Trueequals() を使用する
# 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 errors: pandasライブラリに由来
- DataStore errors: 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パラメータを削除する - 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) |
同じ (実行がトリガーされます) |