polars-bio은(는) 무엇을 하나요?
개요
polars-bio는 Polars, Apache Arrow, Apache DataFusion 기반의 고성능 Python 라이브러리로, 유전체 간격 연산과 생물정보학 파일 I/O를 제공합니다. 간격 산술(중첩, 최근접, 병합, 커버리지, 보완, 차집합) 및 일반적인 생물정보학 형식(BED, VCF, BAM, CRAM, GFF/GTF, FASTA, FASTQ) 읽기/쓰기를 위한 친숙한 DataFrame 중심 API를 제공합니다.
주요 가치 제안:
- 실제 유전체 벤치마크에서 bioframe보다 6~38배 빠름
- DataFusion을 통한 스트리밍/아웃-오브-코어 대용량 유전체 지원
- 클라우드 네이티브 파일 I/O (S3, GCS, Azure) 및 조건자 푸시다운
- 두 가지 API 스타일: 함수형 (
pb.overlap(df1, df2)) 및 메서드 체이닝 (df1.lazy().pb.overlap(df2)) - DataFusion SQL 엔진을 통한 SQL 인터페이스 지원
이 스킬을 사용해야 할 때
다음과 같은 경우 이 스킬을 사용하세요:
- 유전체 간격 연산 수행 (중첩, 최근접, 병합, 커버리지, 보완, 차집합)
- 생물정보학 파일 형식 읽기/쓰기 (BED, VCF, BAM, CRAM, GFF/GTF, FASTA, FASTQ)
- 메모리에 맞지 않는 대용량 유전체 데이터셋 처리 (스트리밍 모드)
- 유전체 데이터 파일에 대한 SQL 쿼리 실행
- bioframe에서 더 빠른 대안으로 마이그레이션
- BAM/CRAM 파일에서 리드 깊이/파일업 계산
- 유전체 간격이 포함된 Polars DataFrame 작업
빠른 시작
설치
Python 3.11–3.14 필요 (PyPI 참조).
uv pip install "polars-bio==0.31.0"
pandas 호환성 (pandas ≥3.0):
uv pip install "polars-bio[pandas]==0.31.0"
기본 중첩 예제
import polars as pl
import polars_bio as pb
# 두 간격 DataFrame 생성
df1 = pl.DataFrame({
"chrom": ["chr1", "chr1", "chr1"],
"start": [1, 5, 22],
"end": [6, 9, 30],
})
df2 = pl.DataFrame({
"chrom": ["chr1", "chr1"],
"start": [3, 25],
"end": [8, 28],
})
# 함수형 API (기본적으로 LazyFrame 반환)
result = pb.overlap(df1, df2)
result_df = result.collect()
# DataFrame 직접 가져오기
result_df = pb.overlap(df1, df2, output_type="polars.DataFrame")
# 메서드 체이닝 API (LazyFrame의 .pb 접근자 사용)
result = df1.lazy().pb.overlap(df2)
result_df = result.collect()
BED 파일 읽기
import polars_bio as pb
# 즉시 읽기 (전체 파일 로드)
df = pb.read_bed("regions.bed")
# 지연 스캔 (스트리밍, 대용량 파일용)
lf = pb.scan_bed("regions.bed")
result = lf.collect()
핵심 기능
1. 유전체 간격 연산
polars-bio는 유전체 범위 산술을 위한 8가지 핵심 간격 연산을 제공합니다. 모든 연산은 chrom, start, end 열이 있는 Polars DataFrame을 허용합니다 (구성 가능). 모든 연산은 기본적으로 LazyFrame을 반환합니다 (즉시 결과를 위해 output_type="polars.DataFrame" 사용).
연산:
overlap/count_overlaps- 두 집합 간 중첩 간격 찾기 또는 개수 세기 (overlap_output="left"는 0.30.0부터 df1 전용 히트 반환)nearest- 가장 가까운 간격 찾기 (구성 가능한k,overlap,distance매개변수 포함)merge- 한 집합 내에서 중첩/연속된 간격 병합cluster- 중첩 간격에 클러스터 ID 할당coverage- 간격별 커버리지 개수 계산 (두 입력 연산)complement- 유전체 내 간격 사이의 간극 찾기subtract- 다른 집합과 중첩되는 간격 부분 제거
예제:
import polars_bio as pb
# 중첩 간격 찾기 (LazyFrame 반환)
result = pb.overlap(df1, df2, suffixes=("_1", "_2"))
# 간격당 중첩 개수 세기
counts = pb.count_overlaps(df1, df2)
# 중첩 간격 병합
merged = pb.merge(df1)
# 가장 가까운 간격 찾기
nearest = pb.nearest(df1, df2)
# 모든 LazyFrame 결과를 DataFrame으로 수집
result_df = result.collect()
참조: 모든 연산, 매개변수, 출력 스키마 및 성능 고려 사항에 대한 자세한 문서는 references/interval_operations.md를 참조하세요.
2. 생물정보학 파일 I/O
read_*, scan_*, write_*, sink_* 함수로 일반적인 생물정보학 형식을 읽고 씁니다. 클라우드 스토리지 (S3, GCS, Azure) 및 압축 (GZIP, BGZF)을 지원합니다.
지원 형식:
- BED - 유전체 간격 (
read_bed,scan_bed,write_*일반 함수 사용) - VCF - 유전 변이 (
read_vcf,scan_vcf,write_vcf,sink_vcf) - VCF Zarr - 분석 준비 Zarr 저장소 (
read_vcf_zarr,scan_vcf_zarr; 로컬 디렉토리 경로) - BAM - 정렬된 리드 (
read_bam,scan_bam,write_bam,sink_bam) - CRAM - 압축된 정렬 (
read_cram,scan_cram,write_cram,sink_cram) - GFF - 유전자 주석 (
read_gff,scan_gff) - GTF - 유전자 주석 (
read_gtf,scan_gtf) - FASTA - 참조 서열 (
read_fasta,scan_fasta,write_fasta,sink_fasta) - FASTQ - 시퀀싱 리드 (
read_fastq,scan_fastq,write_fastq,sink_fastq) - SAM - 텍스트 정렬 (
read_sam,scan_sam,write_sam,sink_sam) - Hi-C pairs - 염색질 접촉 (
read_pairs,scan_pairs)
예제:
import polars_bio as pb
# VCF 파일 읽기
variants = pb.read_vcf("samples.vcf.gz")
# BAM 파일 지연 스캔 (스트리밍)
alignments = pb.scan_bam("aligned.bam")
# GFF 주석 읽기
genes = pb.read_gff("annotations.gff3")
# 클라우드 스토리지 (개별 매개변수, 딕셔너리 아님)
df = pb.read_bed("s3://bucket/regions.bed",
allow_anonymous=True)
참조: 형식별 열 스키마, 매개변수, 클라우드 스토리지 옵션 및 압축 지원에 대해서는 references/file_io.md를 참조하세요.
3. SQL 데이터 처리
생물정보학 파일을 테이블로 등록하고 DataFusion SQL을 사용하여 쿼리합니다. SQL의 강력함과 polars-bio의 유전체 인식 리더를 결합합니다.
import polars as pl
import polars_bio as pb
# 파일을 SQL 테이블로 등록 (경로 먼저, name= 키워드)
pb.register_vcf("samples.vcf.gz", name="variants")
pb.register_bed("target_regions.bed", name="regions")
# SQL로 쿼리 (LazyFrame 반환)
result = pb.sql("SELECT chrom, start, end, ref, alt FROM variants WHERE qual > 30")
result_df = result.collect()
# Polars DataFrame을 SQL 테이블로 등록
pb.from_polars("my_intervals", df)
result = pb.sql("SELECT * FROM my_intervals WHERE chrom = 'chr1'").collect()
참조: 등록 함수, SQL 구문 및 예제는 references/sql_processing.md를 참조하세요.
4. 파일업 연산
BAM/CRAM 파일에서 CIGAR 인식 깊이 계산으로 베이스별 리드 깊이를 계산합니다.
import polars_bio as pb
# BAM 파일 전체에 걸쳐 깊이 계산
depth_lf = pb.depth("aligned.bam")
depth_df = depth_lf.collect()
# 품질 필터 사용
depth_lf = pb.depth("aligned.bam", min_mapping_quality=20)
참조: 매개변수 및 통합 패턴은 references/pileup_operations.md를 참조하세요.
주요 개념
좌표계
polars-bio는 기본적으로 1-기반 좌표(유전체 규약)를 사용합니다. 이는 전역적으로 변경할 수 있습니다:
import polars_bio as pb
# 0-기반 반개방 좌표로 전환 (기본값은 1-기반 / False)
pb.set_option("datafusion.bio.coordinate_system_zero_based", True)
# 1-기반으로 다시 전환 (기본값)
pb.set_option("datafusion.bio.coordinate_system_zero_based", False)
I/O 함수는 use_zero_based 매개변수를 받아 결과 DataFrame에 좌표 메타데이터를 설정합니다:
# 명시적 0-기반 메타데이터로 BED 읽기
df = pb.read_bed("regions.bed", use_zero_based=True)
중요: BED 파일은 파일 형식에서 항상 0-기반 반개방입니다. polars-bio는 BED 파일을 읽을 때 자동으로 변환을 처리합니다. 좌표 메타데이터는 I/O 함수에 의해 DataFrame에 첨부되며 연산을 통해 전파됩니다.
두 가지 API 스타일
함수형 API - 독립 함수, 명시적 입력:
result = pb.overlap(df1, df2, suffixes=("_1", "_2"))
merged = pb.merge(df)
메서드 체이닝 API - LazyFrame의 .pb 접근자 사용 (DataFrame 아님):
result = df1.lazy().pb.overlap(df2)
merged = df.lazy().pb.merge()
중요: 간격 연산을 위한 .pb 접근자는 LazyFrame에서만 사용할 수 있습니다. DataFrame에서 .pb는 쓰기 연산만 제공합니다 (write_bam, write_vcf 등).
메서드 체이닝은 유연한 파이프라인을 가능하게 합니다:
# 간격 연산 체이닝 (참고: overlap은 접미사가 붙은 열을 출력하므로
# chrom/start/end를 예상하는 merge 전에 이름을 바꿔야 함)
result = (
df1.lazy()
.pb.overlap(df2)
.filter(pl.col("start_2") > 1000)
.select(
pl.col("chrom_1").alias("chrom"),
pl.col("start_1").alias("start"),
pl.col("end_1").alias("end"),
)
.pb.merge()
.collect()
)
프로브-빌드 아키텍처
두 입력 연산(overlap, nearest, count_overlaps, coverage)의 경우, polars-bio는 프로브-빌드 조인 전략을 사용합니다:
- 첫 번째 DataFrame은 프로브입니다 (반복됨)
- 두 번째 DataFrame은 빌드입니다 (조회를 위해 인덱싱됨)
최상의 성능을 위해 더 큰 DataFrame을 첫 번째 인수(프로브)로 전달하고 더 작은 DataFrame을 두 번째 인수(빌드)로 전달하세요.
열 규약
기본적으로 polars-bio는 chrom, start, end로 이름이 지정된 열을 예상합니다. 사용자 지정 열 이름은 리스트를 통해 지정할 수 있습니다:
result = pb.overlap(
df1, df2,
cols1=["chromosome", "begin", "finish"],
cols2=["chr", "pos_start", "pos_end"],
)
반환 유형 및 결과 수집
모든 간격 연산 및 pb.sql()은 기본적으로 LazyFrame을 반환합니다. 결과를 구체화하려면 .collect()를 사용하거나, 즉시 평가를 위해 output_type="polars.DataFrame"을 전달하세요:
# 지연 (기본값) - 필요할 때 수집
result_lf = pb.overlap(df1, df2)
result_df = result_lf.collect()
# 즉시 - DataFrame 직접 가져오기
result_df = pb.overlap(df1, df2, output_type="polars.DataFrame")
스트리밍 및 아웃-오브-코어 처리
사용 가능한 RAM보다 큰 데이터셋의 경우 scan_* 함수와 스트리밍 실행을 사용하세요:
# 파일을 지연 스캔
lf = pb.scan_bed("large_intervals.bed")
# Polars 스트리밍으로 처리 (polars ≥1.37 필요, polars-bio와 번들됨)
result = lf.collect(engine="streaming")
DataFusion 스트리밍은 간격 연산에 대해 기본적으로 활성화되어 있으며, 전체 데이터셋을 메모리에 로드하지 않고 배치 단위로 데이터를 처리합니다.
일반적인 함정
-
DataFrame과 LazyFrame에서의
.pb접근자: 간격 연산(overlap, merge 등)은LazyFrame.pb에서만 사용할 수 있습니다.DataFrame.pb에는 쓰기 메서드만 있습니다. 간격 연산 체이닝 전에.lazy()를 사용하여 변환하세요. -
LazyFrame 반환: 모든 간격 연산 및
pb.sql()은 기본적으로LazyFrame을 반환합니다..collect()를 잊지 말거나output_type="polars.DataFrame"을 사용하세요. -
열 이름 불일치: polars-bio는 기본적으로
chrom,start,end를 예상합니다. 열 이름이 다른 경우cols1/cols2매개변수(리스트로)를 사용하세요. -
좌표계 메타데이터: 간격 연산은 I/O 함수 또는 DataFrame
config_meta에서 좌표 메타데이터를 읽습니다. 수동으로 만든 DataFrame의 경우df.config_meta.set(coordinate_system_zero_based=True)(0-기반) 또는False(1-기반)를 설정하세요. 메타데이터가 없으면 polars-bio는 전역datafusion.bio.coordinate_system_zero_based설정으로 대체됩니다 (경고 포함).pb.set_option("datafusion.bio.coordinate_system_check", True)를 설정하여 대신MissingCoordinateSystemError를 발생시킵니다. 입력 간 시스템 불일치는CoordinateSystemMismatchError를 발생시킵니다. -
프로브-빌드 순서 중요: overlap, nearest, coverage의 경우 첫 번째 DataFrame이 두 번째 DataFrame에 대해 프로브됩니다. 인수를 바꾸면 왼쪽 및 오른쪽 출력 열에 나타나는 간격이 변경되고 성능에 영향을 줄 수 있습니다.
-
INT32 위치 제한: 유전체 위치는 32비트 정수로 저장되므로 좌표가 약 21억 개로 제한됩니다. 이는 알려진 모든 유전체에 충분하지만 사용자 지정 좌표 공간에서는 문제가 될 수 있습니다.
-
BAM 인덱스 요구 사항:
read_bam및scan_bam은 BAM 파일과 함께.bai인덱스 파일이 필요합니다. 누락된 경우samtools index로 생성하세요. -
병렬 실행 기본 비활성화: DataFusion 병렬 처리는 기본적으로 1개 파티션입니다. 대용량 데이터셋의 경우 활성화하세요:
pb.set_option("datafusion.execution.target_partitions", 8) -
CRAM에는 별도 함수 사용: CRAM 파일에는
read_cram/scan_cram/register_cram을 사용하세요 (read_bam아님). CRAM 함수는reference_path매개변수가 필요합니다.
모범 사례
-
대용량 파일에는
scan_*사용: 사용 가능한 RAM보다 큰 파일의 경우read_*보다scan_bed,scan_vcf등을 선호하세요. 스캔 함수는 스트리밍 및 조건자 푸시다운을 활성화합니다. -
대용량 데이터셋에 대해 병렬 처리 구성:
import os pb.set_option("datafusion.execution.target_partitions", os.cpu_count()) -
BGZF 압축 사용: BGZF 압축 파일(
.bed.gz,.vcf.gz)은 병렬 블록 압축 해제를 지원하여 일반 GZIP보다 훨씬 빠릅니다. -
초기에 열 선택: 특정 열만 필요한 경우 초기에 선택하여 메모리 사용량을 줄이세요:
df = pb.read_vcf("large.vcf.gz").select("chrom", "start", "end", "ref", "alt") -
클라우드 경로 직접 사용: S3/GCS/Azure URI를 read/scan/register 함수에 직접 전달하여 파일을 먼저 다운로드하지 마세요. 인증된 액세스는 해당 클라우드 경로에 액세스할 때만 클라우드 SDK 자격 증명(
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY,GOOGLE_APPLICATION_CREDENTIALS, Azure 기본값)을 사용합니다:df = pb.read_bed("s3://my-bucket/regions.bed", allow_anonymous=True) -
단일 연산에는 함수형 API, 파이프라인에는 메서드 체이닝 선호: 한 번만 사용하는 연산에는
pb.overlap()을 사용하고, 다단계 파이프라인을 구축할 때는.lazy().pb.overlap()을 사용하세요.
리소스
references/
각 주요 기능에 대한 자세한 문서:
-
interval_operations.md - 모든 8가지 간격 연산, 매개변수, 예제, 출력 스키마 및 성능 팁. 유전체 범위 산술의 핵심 참조.
-
file_io.md - 지원 형식 표, 형식별 열 스키마,