polars-bio は何をしますか?
概要
polars-bioは、Polars、Apache Arrow、Apache DataFusion上に構築された、ゲノム間隔演算とバイオインフォマティクスファイル入出力のための高性能Pythonライブラリです。間隔演算(オーバーラップ、最近傍検索、マージ、カバレッジ、補完、減算)と、一般的なバイオインフォマティクス形式(BED、VCF、BAM、CRAM、GFF/GTF、FASTA、FASTQ)の読み書きのための、使い慣れたデータフレーム中心のAPIを提供します。
主な価値提案:
- 実際のゲノムベンチマークでbioframeより6〜38倍高速
- DataFusionによるストリーミング/アウトオブコアサポート(大規模ゲノム対応)
- クラウドネイティブなファイルI/O(S3、GCS、Azure)、述語プッシュダウン対応
- 2つの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データフレームの操作
クイックスタート
インストール
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
# 2つの間隔データフレームを作成
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データフレームを受け入れます(カスタムカラム名設定可能)。すべての演算はデフォルトでLazyFrameを返します(即時評価にはoutput_type="polars.DataFrame"を使用)。
演算:
overlap/count_overlaps- 2つのセット間の重複間隔の検索またはカウント(overlap_output="left"はバージョン0.30.0以降、df1のみのヒットを返します)nearest- 最近傍間隔の検索(k、overlap、distanceパラメータ設定可能)merge- セット内の重複/隣接間隔のマージcluster- 重複間隔へのクラスターID割り当てcoverage- 間隔ごとのカバレッジカウントの計算(2入力演算)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データフレームを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を受け入れ、結果のデータフレームに座標メタデータを設定します:
# 明示的な0ベースメタデータでBEDを読み込み
df = pb.read_bed("regions.bed", use_zero_based=True)
重要: BEDファイルはファイル形式として常に0ベース半開です。polars-bioはBEDファイル読み込み時に自動的に変換を処理します。座標メタデータはI/O関数によってデータフレームにアタッチされ、演算を通じて伝播されます。
2つのAPIスタイル
関数型API - スタンドアロン関数、明示的な入力:
result = pb.overlap(df1, df2, suffixes=("_1", "_2"))
merged = pb.merge(df)
メソッドチェーンAPI - LazyFrame(データフレームではない)上の.pbアクセサ経由:
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()
)
プローブビルドアーキテクチャ
2入力演算(オーバーラップ、最近傍検索、カウント、カバレッジ)では、polars-bioはプローブビルド結合戦略を使用します:
- 最初のデータフレームはプローブ(反復処理される)
- 2番目のデータフレームはビルド(ルックアップ用にインデックス付けされる)
最適なパフォーマンスを得るには、より大きなデータフレームを最初の引数(プローブ)として、より小さなものを2番目(ビルド)として渡します。
カラム規則
デフォルトでは、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"を渡します:
# 遅延(デフォルト) - 必要なときにcollect
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から座標メタデータを読み取ります。手動で作成したデータフレームの場合は、df.config_meta.set(coordinate_system_zero_based=True)(0ベース)またはFalse(1ベース)を設定します。メタデータがない場合、polars-bioはグローバルなdatafusion.bio.coordinate_system_zero_based設定にフォールバックします(警告あり)。代わりにMissingCoordinateSystemErrorを発生させるには、pb.set_option("datafusion.bio.coordinate_system_check", True)を設定します。入力間でシステムが一致しない場合は、CoordinateSystemMismatchErrorが発生します。 -
プローブビルドの順序が重要: オーバーラップ、最近傍検索、カバレッジでは、最初のデータフレームが2番目のデータフレームに対してプローブされます。引数を入れ替えると、左と右の出力カラムにどの間隔が表示されるかが変わり、パフォーマンスに影響を与える可能性があります。
-
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_bamではなく)read_cram/scan_cram/register_cramを使用してください。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を読み取り/スキャン/登録関数に直接渡します。認証アクセスは、クラウドパスにアクセスされた場合にのみ、クラウド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、パイプラインにはメソッドチェーンを優先: 1回限りの操作には
pb.overlap()を、複数ステップのパイプラインを構築する場合には.lazy().pb.overlap()を使用します。
リソース
references/
各主要機能の詳細ドキュメント:
-
interval_operations.md - パラメータ、例、出力スキーマ、パフォーマンスのヒントを含む、8つのすべての間隔演算。ゲノム範囲演算のコアリファレンス。
-
file_io.md - サポートされている形式の表、形式ごとのカラムスキーマ、
(続くが翻訳対象外)