데이터 수집

데이터 수집 (Data Ingestion)

이 페이지는 DuckDB를 사용해 Python으로 데이터를 수집(ingestion)하는 예시를 담고 있어요. 먼저 DuckDB 패키지를 임포트해요.

import duckdb

그런 다음 아래 섹션 중 원하는 것으로 진행해요.

출처: 문서

본문

CSV 파일

CSV 파일은 read_csv 함수로 읽을 수 있어요. Python에서 또는 SQL에서 직접 호출할 수 있어요. 기본적으로 read_csv 함수는 제공된 파일을 샘플링해 CSV 설정을 자동 감지하려 해요.

완전 자동 감지 설정으로 파일 읽기:

duckdb.read_csv("example.csv")

폴더에서 여러 CSV 파일 읽기:

duckdb.read_csv("folder/*.csv")

CSV가 내부적으로 어떻게 포맷되는지 옵션 지정:

duckdb.read_csv("example.csv", header = False, sep = ",")

처음 두 열의 타입 덮어쓰기:

duckdb.read_csv("example.csv", dtype = ["int", "varchar"])

SQL 안에서 CSV 파일 직접 읽기:

duckdb.sql("SELECT * FROM 'example.csv'")

SQL 안에서 read_csv 호출:

duckdb.sql("SELECT * FROM read_csv('example.csv')")

자세한 내용은 [CSV Import]({% link docs/current/data/csv/overview.md %}) 페이지를 참고하세요.

Parquet 파일

Parquet 파일은 read_parquet 함수로 읽을 수 있어요. Python에서 또는 SQL에서 직접 호출할 수 있어요.

단일 Parquet 파일 읽기:

duckdb.read_parquet("example.parquet")

폴더에서 여러 Parquet 파일 읽기:

duckdb.read_parquet("folder/*.parquet")

[https]({% link docs/current/core_extensions/httpfs/overview.md %})로 Parquet 파일 읽기:

duckdb.read_parquet("https://some.url/some_file.parquet")

Parquet 파일 목록 읽기:

duckdb.read_parquet(["file1.parquet", "file2.parquet", "file3.parquet"])

SQL 안에서 Parquet 파일 직접 읽기:

duckdb.sql("SELECT * FROM 'example.parquet'")

SQL 안에서 read_parquet 호출:

duckdb.sql("SELECT * FROM read_parquet('example.parquet')")

자세한 내용은 [Parquet Loading]({% link docs/current/data/parquet/overview.md %}) 페이지를 참고하세요.

JSON 파일

JSON 파일은 read_json 함수로 읽을 수 있어요. Python에서 또는 SQL에서 직접 호출할 수 있어요. 기본적으로 read_json 함수는 파일이 줄바꿈 구분 JSON인지 일반 JSON인지 자동 감지하고, JSON 파일 안에 저장된 객체의 스키마도 감지해요.

단일 JSON 파일 읽기:

duckdb.read_json("example.json")

폴더에서 여러 JSON 파일 읽기:

duckdb.read_json("folder/*.json")

SQL 안에서 JSON 파일 직접 읽기:

duckdb.sql("SELECT * FROM 'example.json'")

SQL 안에서 read_json 호출:

duckdb.sql("SELECT * FROM read_json('example.json')")

DataFrame과 Arrow 객체 직접 접근

DuckDB는 변수 이름을 참조해(마치 테이블인 것처럼) 특정 Python 변수를 자동으로 쿼리할 수 있어요. 이런 타입에는 Pandas DataFrame, Polars DataFrame, Polars LazyFrame, NumPy 배열, [relations]({% link docs/current/clients/python/relational_api.md %}) 그리고 Arrow 객체가 포함돼요.

sql() 또는 execute() 호출 위치에서 Python 코드에 보이는 변수만 이런 방식으로 사용할 수 있어요. 이런 변수에 접근하는 것은 [replacement scans]({% link docs/current/clients/c/replacement_scans.md %}) 덕분에 가능해요. replacement scan을 완전히 비활성화하려면:

SET python_enable_replacements = false;

DuckDB는 tables, datasets, RecordBatchReaders, scanners를 포함한 여러 Apache Arrow 객체 타입 쿼리를 지원해요. 더 많은 예시는 Python [guides]({% link docs/current/guides/overview.md %}#python-client)를 참고하세요.

import duckdb
import pandas as pd

test_df = pd.DataFrame.from_dict({"i": [1, 2, 3, 4], "j": ["one", "two", "three", "four"]})
print(duckdb.sql("SELECT * FROM test_df").fetchall())
[(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]

DuckDB는 DataFrame이나 Arrow 객체를 SQL VIEW에 비길 만한 가상 테이블로 "등록(register)"하는 것도 지원해요. 다른 방식으로 저장된 (클래스 변수나 사전의 값으로) DataFrame/Arrow 객체를 쿼리할 때 유용해요. 다음은 Pandas 예시예요.

Pandas DataFrame이 다른 위치에 저장되어 있다면 수동으로 등록하는 예시예요.

import duckdb
import pandas as pd

my_dictionary = {}
my_dictionary["test_df"] = pd.DataFrame.from_dict({"i": [1, 2, 3, 4], "j": ["one", "two", "three", "four"]})
duckdb.register("test_df_view", my_dictionary["test_df"])
print(duckdb.sql("SELECT * FROM test_df_view").fetchall())
[(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]

DataFrame(또는 뷰)의 내용으로 DuckDB에 영구 테이블을 만들 수도 있어요.

# create a new table from the contents of a DataFrame
con.execute("CREATE TABLE test_df_table AS SELECT * FROM test_df")
# insert into an existing table from the contents of a DataFrame
con.execute("INSERT INTO test_df_table SELECT * FROM test_df")

같은 이름을 가진 객체의 우선순위는 다음과 같아요.

  • register()로 명시적으로 등록된 객체
  • 네이티브 DuckDB 테이블과 뷰
  • [Replacement scans]({% link docs/current/clients/c/replacement_scans.md %})

Pandas DataFrame – object

pandas.DataFrameobject dtype 열은 임의 타입의 값을 저장하므로 특별한 주의가 필요해요. 이런 열을 DuckDB로 변환할 때 먼저 analyze 단계를 거친 뒤 값을 변환해요. 이 analyze 단계에서 열의 모든 행의 샘플을 분석해 대상 타입을 결정해요. 이 샘플 크기는 기본 1000으로 설정돼요. analyze 단계에서 고른 타입이 틀리면 Invalid Input Error: Failed to cast value가 나는데, 이때는 샘플 크기를 늘려야 해요. 샘플 크기는 pandas_analyze_sample 설정 옵션으로 바꿀 수 있어요.

# example setting the sample size to 100k
duckdb.execute("SET GLOBAL pandas_analyze_sample = 100_000")

더 알아보기 (Learn more)