> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# pandas와의 주요 차이점

> DataStore와 pandas의 주요 차이점

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

<div id="summary">
  ## 요약 표
</div>

| Aspect      | pandas           | DataStore                                                                     |
| ----------- | ---------------- | ----------------------------------------------------------------------------- |
| **실행**      | Eager (즉시 실행)    | Lazy (지연 실행)                                                                  |
| **반환 타입**   | DataFrame/Series | DataStore/ColumnExpr                                                          |
| **행 순서**    | 유지됨              | 유지됨(자동); [성능 모드](/ko/products/chdb/configuration/performance-mode)에서는 보장되지 않음 |
| **inplace** | 지원됨              | 지원되지 않음                                                                       |
| **인덱스**     | 완전 지원            | 단순화됨                                                                          |
| **메모리**     | 모든 데이터가 메모리에 있음  | 데이터가 소스에 유지됨                                                                  |

***

<div id="lazy-execution">
  ## 1. 지연 실행 vs 즉시 실행
</div>

<div id="pandas-eager">
  ### pandas (즉시 실행)
</div>

연산이 바로 실행됩니다:

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

df = pd.read_csv("data.csv")  # 전체 파일을 즉시 로드
result = df[df['age'] > 25]   # 즉시 필터링
grouped = result.groupby('city')['salary'].mean()  # 즉시 집계
```

<div id="datastore-lazy">
  ### DataStore (지연 실행)
</div>

연산은 결과가 필요할 때까지 지연됩니다:

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

ds = pd.read_csv("data.csv")  # 소스만 기록
result = ds[ds['age'] > 25]   # 필터만 기록
grouped = result.groupby('city')['salary'].mean()  # 연산만 기록

# 실행은 여기서 시작:
print(grouped)        # 출력 시 실행
df = grouped.to_df()  # 또는 pandas로 변환 시 실행
```

<div id="why-lazy">
  ### 왜 중요한가
</div>

지연 실행은 다음과 같은 이점을 제공합니다:

* **쿼리 최적화**: 여러 작업이 하나의 SQL 쿼리로 컴파일됩니다
* **컬럼 프루닝(Column pruning)**: 필요한 컬럼만 읽습니다
* **필터 푸시다운(Filter pushdown)**: 필터를 소스에 적용합니다
* **메모리 효율성**: 필요하지 않은 데이터는 로드하지 않습니다

***

<div id="return-types">
  ## 2. 반환 타입
</div>

<div id="pandas-return-types">
  ### pandas
</div>

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

<div id="datastore-return-types">
  ### DataStore
</div>

```python theme={null}
ds['col']           # ColumnExpr 반환 (지연 실행)
ds[['a', 'b']]      # DataStore 반환 (지연 실행)
ds[ds['x'] > 10]    # DataStore 반환 (지연 실행)
ds.groupby('x')     # LazyGroupBy 반환
```

<div id="converting-to-pandas-types">
  ### pandas 타입으로 변환하기
</div>

```python theme={null}
# pandas DataFrame 가져오기
df = ds.to_df()
df = ds.to_pandas()

# 컬럼에서 pandas Series 가져오기
series = ds['col'].to_pandas()

# 또는 실행 트리거
print(ds)  # 표시를 위해 자동으로 변환
```

***

<div id="triggers">
  ## 3. 실행 트리거
</div>

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)` | 비교가 필요합니다        |

<div id="stay-lazy">
  ### 지연 실행로 유지되는 작업
</div>

| 작업               | 반환값         |
| ---------------- | ----------- |
| `filter()`       | DataStore   |
| `select()`       | DataStore   |
| `sort()`         | DataStore   |
| `groupby()`      | LazyGroupBy |
| `join()`         | DataStore   |
| `ds['col']`      | ColumnExpr  |
| `ds[['a', 'b']]` | DataStore   |
| `ds[condition]`  | DataStore   |

***

<div id="row-order">
  ## 4. 행 순서
</div>

<div id="pandas-return-types">
  ### pandas
</div>

행의 순서는 항상 유지됩니다:

```python theme={null}
df = pd.read_csv("data.csv")
print(df.head())  # 항상 파일과 동일한 순서 유지
```

<div id="datastore-return-types">
  ### DataStore
</div>

대부분의 작업에서 행 순서는 **자동으로 유지됩니다**:

```python theme={null}
ds = pd.read_csv("data.csv")
print(ds.head())  # 파일 순서와 일치

# 필터 적용 후에도 순서 유지
ds_filtered = ds[ds['age'] > 25]  # pandas와 동일한 순서
```

DataStore는 pandas와의 순서 일관성을 보장하기 위해 내부적으로 원래 행 위치를 `rowNumberInAllBlocks()`를 사용해 자동으로 추적합니다.

<div id="order-preserved">
  ### 순서가 유지되는 경우
</div>

* 파일 소스(CSV, Parquet, JSON 등)
* pandas DataFrame 소스
* 필터링 작업
* 컬럼 선택
* 명시적으로 `sort()` 또는 `sort_values()`를 수행한 후
* 순서를 결정하는 작업(`nlargest()`, `nsmallest()`, `head()`, `tail()`)

<div id="order-may-differ">
  ### 순서가 달라질 수 있는 경우
</div>

* `groupby()` 집계 후(`sort_values()`를 사용하면 일관된 순서를 유지할 수 있습니다)
* 특정 join 유형으로 `merge()` / `join()`을 수행한 후
* **성능 모드**(`config.use_performance_mode()`)에서는 어떤 작업에서도 행 순서가 보장되지 않습니다. [성능 모드](/ko/products/chdb/configuration/performance-mode)를 참조하십시오.

***

<div id="no-inplace">
  ## 5. inplace 매개변수 미지원
</div>

<div id="pandas-return-types">
  ### pandas
</div>

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

<div id="datastore-return-types">
  ### DataStore
</div>

`inplace=True`는 지원되지 않습니다. 결과는 항상 다시 할당하세요:

```python theme={null}
ds = ds.drop(columns=['col'])           # 새로운 DataStore를 반환합니다
ds = ds.fillna(0)                       # 새로운 DataStore를 반환합니다
ds = ds.rename(columns={'old': 'new'})  # 새로운 DataStore를 반환합니다
```

<div id="why-no-inplace">
  ### 왜 inplace를 지원하지 않나요?
</div>

DataStore는 다음을 지원하기 위해 불변 연산을 사용합니다:

* 쿼리 작성(lazy evaluation)
* 스레드 안전성
* 디버깅 용이성
* 더 깔끔한 코드

***

<div id="index">
  ## 6. 인덱스 지원
</div>

<div id="pandas-return-types">
  ### pandas
</div>

모든 인덱스를 지원합니다:

```python theme={null}
df = df.set_index('id')
df.loc['user123']           # 레이블 기반 접근
df.loc['a':'z']             # 레이블 기반 슬라이싱
df.reset_index()
df.index.name = 'user_id'
```

<div id="datastore-return-types">
  ### DataStore
</div>

간편한 인덱스 지원:

```python theme={null}
# 기본 작업 가능
ds.loc[0:10]               # 정수 위치
ds.iloc[0:10]              # DataStore에서 loc과 동일

# pandas 스타일 인덱스 작업의 경우 먼저 변환
df = ds.to_df()
df = df.set_index('id')
df.loc['user123']
```

<div id="datastore-source-matters">
  ### DataStore에서는 소스가 중요합니다
</div>

* **DataFrame 소스**: pandas 인덱스가 유지됩니다
* **File 소스**: 단순한 정수 인덱스를 사용합니다

***

<div id="comparison">
  ## 7. 비교 방식
</div>

<div id="comparing-with-pandas">
  ### pandas와의 비교
</div>

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]})

# 예상대로 동작하지 않음
pdf == dsf  # pandas는 DataStore를 인식하지 못함

# 해결 방법: DataStore를 pandas로 변환
pdf.equals(dsf.to_pandas())  # True
```

<div id="using-equals">
  ### equals() 사용하기
</div>

```python theme={null}
# DataStore.equals()도 작동합니다
dsf.equals(pdf)  # pandas DataFrame과 비교합니다
```

***

<div id="types">
  ## 8. 타입 추론
</div>

<div id="pandas-return-types">
  ### pandas
</div>

numpy/pandas의 타입을 사용합니다:

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

<div id="datastore-return-types">
  ### DataStore
</div>

ClickHouse 타입을 사용할 수 있습니다:

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

# pandas로 변환 시 타입이 변환됩니다
df = ds.to_df()
df['col'].dtype  # 이제 pandas 타입
```

<div id="explicit-casting">
  ### 명시적 형 변환
</div>

```python theme={null}
# 특정 유형으로 강제 변환
ds['col'] = ds['col'].astype('int64')
```

***

<div id="memory">
  ## 9. 메모리 모델
</div>

<div id="pandas-return-types">
  ### pandas
</div>

모든 데이터가 메모리에 상주합니다:

```python theme={null}
df = pd.read_csv("huge.csv")  # 메모리에 10GB!
```

<div id="datastore-return-types">
  ### DataStore
</div>

데이터는 필요할 때까지 원본에 그대로 유지됩니다:

```python theme={null}
ds = pd.read_csv("huge.csv")  # 메타데이터뿐
ds = ds.filter(ds['year'] == 2024)  # 여전히 메타데이터뿐

# 필터링된 결과만 불러옵니다
df = ds.to_df()  # 이제 1GB 정도일 수도 있음
```

***

<div id="errors">
  ## 10. 오류 메시지
</div>

<div id="different-error-sources">
  ### 다양한 오류 발생 원인
</div>

* **pandas 오류**: pandas 라이브러리에서 발생
* **DataStore 오류**: chDB 또는 ClickHouse에서 발생

```python theme={null}
# ClickHouse 스타일의 오류가 표시될 수 있습니다
# "Code: 62. DB::Exception: Syntax error..."
```

<div id="debugging-tips">
  ### 디버깅 팁
</div>

```python theme={null}
# 디버깅을 위해 SQL 확인
print(ds.to_sql())

# 실행 계획 확인
ds.explain()

# 디버그 로깅 활성화
from chdb.datastore.config import config
config.enable_debug()
```

***

<div id="checklist">
  ## 마이그레이션 체크리스트
</div>

pandas에서 마이그레이션할 때:

* [ ] import 문 변경
* [ ] `inplace=True` 매개변수 제거
* [ ] pandas DataFrame이 필요한 경우 `to_df()`를 명시적으로 추가
* [ ] 행 순서가 중요하면 정렬 추가
* [ ] 비교 테스트에는 `to_pandas()` 사용
* [ ] 실제와 유사한 데이터 크기로 테스트

***

<div id="quick-ref">
  ## 빠른 참고
</div>

| 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)`               | 동일(실행 트리거)                     |
