Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

pandas와의 주요 차이점

DataStore는 pandas와 매우 높은 호환성을 제공하지만, 알아두어야 할 중요한 차이점이 있습니다.

요약 표

항목 pandas DataStore
실행 방식 Eager (즉시 실행) Lazy (지연 실행)
반환 타입 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 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 쿼리로 컴파일합니다
  • 컬럼 프루닝: 필요한 컬럼만 읽습니다
  • 필터 푸시다운: 필터를 원본 데이터 소스에서 적용합니다
  • 메모리 효율성: 필요하지 않은 데이터는 로드하지 않습니다

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는 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())  # 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 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) 동일함(실행 트리거)
Navigation