OmicsLakeは、バイオインフォマティクスデータ解析のための 包括的なバージョン管理・依存関係追跡システムを提供する Rパッケージです。 このビネットでは、全ての主要機能を実例とともに紹介します。
このビネットは、パッケージチェック時の安定性のため既定で非評価設定です。 ローカルで全チャンクを実行するには、以下を先に設定してください。
RNA-seqの代表フロー(count -> edgeR -> limma-voom -> ORA)を即時に試す場合は、以下のスクリプトを使えます。
レイヤー別の代表ユースケース(SE/SCE/MAE/Spectra/QFeatures/MsExperiment) は次のビネットに整理しています。
vignettes/omicslake_layer_use_cases.Rmdol_init()
は指定した名前でプロジェクトを作成し、DuckDBデータベースを初期化します。
# サンプルデータの作成
set.seed(123)
raw_counts <- data.frame(
gene_id = paste0("GENE", 1:100),
sample1 = rpois(100, 100),
sample2 = rpois(100, 100),
sample3 = rpois(100, 120),
sample4 = rpois(100, 120)
)
# テーブルとして保存
ol_write("raw_counts", raw_counts, mode = "create")
# テーブルの読み込み
counts <- ol_read("raw_counts")
head(counts)
# テーブル一覧の確認
ol_list_tables()出力の見方: ol_list_tables()
は現在のプロジェクトに保存されているすべてのテーブル名を返します。
ol_query() を使用すると、DuckDBの全機能
(JOIN、集計、ウィンドウ関数など)を活用した
高度なデータ分析が可能です。
# 基本的なクエリ
result <- ol_query("SELECT * FROM raw_counts WHERE sample1 > 100")
head(result)
# 集計クエリ
summary <- ol_query("
SELECT
COUNT(*) as total_genes,
AVG(sample1) as avg_sample1,
MAX(sample1) as max_sample1
FROM raw_counts
")
print(summary)# テーブルのJOIN(例:遺伝子情報との結合)
ol_write("gene_annotations", data.frame(
gene_id = paste0("gene", 1:5),
name = paste0("GeneA", 1:5),
chromosome = c("chr1", "chr2", "chr1", "chr3", "chr2")
))
joined <- ol_query("
SELECT r.gene_id, r.sample1, a.name, a.chromosome
FROM raw_counts r
JOIN gene_annotations a ON r.gene_id = a.gene_id
WHERE r.sample1 > 50
")
head(joined)# collect=FALSE で遅延評価
if (requireNamespace("dplyr", quietly = TRUE)) {
lazy_tbl <- ol_query("SELECT * FROM raw_counts", collect = FALSE)
# dplyrパイプラインで処理
result <- lazy_tbl %>%
dplyr::filter(sample1 > 100) %>%
dplyr::select(gene_id, sample1, sample2) %>%
dplyr::arrange(dplyr::desc(sample1)) %>%
dplyr::collect()
head(result)
}注意: テーブル名は ol.
プレフィックスなしで参照できます(例: genes
でOK、ol.genes も使用可能)。 ## 1.4
集計・ウィンドウ関数による高度な分析
フェーズ2の関数を使用すると、 一般的な集計やウィンドウ関数の操作がより簡単になります。 これらの関数は、DuckDBの高度な分析機能を活用して、 遺伝子発現データの統計処理を効率化します。
# サンプル全体の統計
overall_stats <- ol_aggregate("raw_counts",
mean_sample1 = list(func = "avg", col = "sample1"),
median_sample1 = list(func = "median", col = "sample1"),
sd_sample1 = list(func = "stddev", col = "sample1")
)
print(overall_stats)
# グループごとの統計(例:サンプル1が高発現 vs 低発現)
# まず高発現/低発現のカテゴリを追加
ol_query("
CREATE OR REPLACE TABLE raw_counts_categorized AS
SELECT *,
CASE WHEN sample1 > 100 THEN 'high' ELSE 'low' END as expr_category
FROM raw_counts
")
grouped_stats <- ol_aggregate("raw_counts_categorized",
group_by = "expr_category",
count = list(func = "count", col = "*"),
mean_s1 = list(func = "avg", col = "sample1"),
mean_s2 = list(func = "avg", col = "sample2")
)
print(grouped_stats)# 発現量で遺伝子をランク付け
ranked_genes <- ol_add_rank("raw_counts",
rank_by = "sample1",
method = "row_number",
descending = TRUE,
as_column = "expression_rank"
)
head(ranked_genes)
# トップ10遺伝子を取得
top_genes <- ol_top_n("raw_counts",
n = 10,
order_by = "sample1",
descending = TRUE
)
print(top_genes)
# サンプルごとのトップ5遺伝子
# まずデータを縦型に変換
ol_query("
CREATE OR REPLACE TABLE raw_counts_long AS
SELECT gene_id, 'sample1' as sample, sample1 as expression FROM raw_counts
UNION ALL
SELECT gene_id, 'sample2' as sample, sample2 as expression FROM raw_counts
UNION ALL
SELECT gene_id, 'sample3' as sample, sample3 as expression FROM raw_counts
UNION ALL
SELECT gene_id, 'sample4' as sample, sample4 as expression FROM raw_counts
")
top_per_sample <- ol_top_n("raw_counts_long",
n = 5,
order_by = "expression",
partition_by = "sample",
descending = TRUE
)
print(top_per_sample)# 移動平均(スムージング)
# 遺伝子IDでソートして3遺伝子の移動平均を計算
smoothed <- ol_moving_avg("raw_counts",
column = "sample1",
window_size = 3,
order_by = "gene_id",
as_column = "sample1_smoothed"
)
head(smoothed, 10)
# より大きなウィンドウサイズ
smoothed_5 <- ol_moving_avg("raw_counts",
column = "sample1",
window_size = 5,
order_by = "gene_id",
as_column = "sample1_ma5"
)
head(smoothed_5, 10)
# 累積和(遺伝子IDでソートして累積カウント)
cumulative <- ol_cumulative_sum("raw_counts",
column = "sample1",
order_by = "gene_id",
as_column = "sample1_cumsum"
)
head(cumulative, 10)
tail(cumulative)
# サンプルごとの累積和(縦型データを使用)
cumulative_per_sample <- ol_cumulative_sum("raw_counts_long",
column = "expression",
partition_by = "sample",
order_by = "gene_id",
as_column = "cumulative_expr"
)
head(cumulative_per_sample, 20)# 集計関数も遅延評価をサポート
if (requireNamespace("dplyr", quietly = TRUE)) {
# 遅延評価で統計を計算
lazy_stats <- ol_aggregate("raw_counts",
mean_s1 = list(func = "avg", col = "sample1"),
collect = FALSE
)
# さらにdplyrで処理
result <- lazy_stats %>%
dplyr::collect()
print(result)
# ランキングと組み合わせ
lazy_ranked <- ol_add_rank("raw_counts",
rank_by = "sample1",
as_column = "rank",
collect = FALSE
)
top_ranked <- lazy_ranked %>%
dplyr::filter(rank <= 10) %>%
dplyr::select(gene_id, sample1, rank) %>%
dplyr::arrange(rank) %>%
dplyr::collect()
print(top_ranked)
}これらの関数を使用することで、 複雑なSQLを書かずに一般的な分析パターンを簡単に実行できます。
# 正規化係数を計算(例)
norm_factors <- list(
method = "TMM",
factors = runif(100, 0.8, 1.2)
)
# Rオブジェクトとして保存
ol_save("norm_factors", norm_factors)
# オブジェクトの読み込み
loaded_factors <- ol_read_object("norm_factors")
str(loaded_factors)
# オブジェクト一覧の確認
ol_list_objects()出力の見方: ol_list_objects()
は保存されているすべてのRオブジェクト名を返します。
# 正規化されたカウントを計算(depends_on で依存関係を指定)
normalized_counts <- raw_counts
for (i in 2:5) {
normalized_counts[[i]] <- normalized_counts[[i]] * norm_factors$factors
}
# 依存関係を指定して保存
ol_write("normalized_counts", normalized_counts,
depends_on = c("raw_counts", "norm_factors")
)
# DEパラメータを保存
de_params <- list(
method = "DESeq2",
alpha = 0.05,
lfc_threshold = 1.0
)
ol_save("de_params", de_params)
# DE結果を計算(簡略化した例)
de_results <- data.frame(
gene_id = paste0("GENE", 1:20),
log2FC = rnorm(20, 0, 2),
pvalue = runif(20, 0, 0.1),
padj = runif(20, 0, 0.1)
)
# DE結果を依存関係付きで保存
ol_save("de_results", de_results,
depends_on = c("normalized_counts", "de_params")
)# 上流の依存関係(このオブジェクトが依存しているもの)
upstream <- ol_get_dependencies("de_results", direction = "upstream")
print(upstream)
# 下流の依存関係(このオブジェクトに依存しているもの)
downstream <- ol_get_dependencies("raw_counts", direction = "downstream")
print(downstream)
# 完全な系統樹を表示
lineage <- ol_show_lineage("de_results", direction = "upstream")
print(lineage)出力の見方:
ol_get_dependencies():
直接の依存関係をdata.frameで返しますol_show_lineage():
再帰的に全ての祖先/子孫を探索し、完全な系統樹を返しますOmicsLakeは、DuckDBの高性能Parquetサポートを活用して、 テーブルを効率的にParquetファイルにエクスポートしたり、 Parquetファイルからインポートしたりできます。
# 基本的なエクスポート(デフォルトはSnappy圧縮)
ol_export_parquet("genes", "genes.parquet")
# zstd圧縮でエクスポート(高圧縮率)
ol_export_parquet("genes", "genes_zstd.parquet",
compression = "zstd",
compression_level = 3
)
# 行グループサイズを指定してエクスポート
ol_export_parquet("genes", "genes_optimized.parquet",
compression = "zstd",
row_group_size = 50000
)
# 圧縮なしでエクスポート(最速)
ol_export_parquet("genes", "genes_uncompressed.parquet",
compression = "uncompressed"
)# Parquetファイルからテーブルを作成
ol_import_parquet("genes.parquet", "imported_genes", mode = "create")
# 既存のテーブルを上書き
ol_import_parquet("genes_new.parquet", "genes", mode = "overwrite")
# 既存のテーブルにデータを追加
ol_import_parquet("genes_batch2.parquet", "genes", mode = "append")
# 複数のParquetファイルを一度にインポート
ol_import_parquet(c("genes_part1.parquet", "genes_part2.parquet"),
"all_genes",
mode = "create"
)
# 依存関係を記録してインポート
ol_import_parquet("processed_genes.parquet",
"final_genes",
depends_on = "raw_genes",
mode = "create"
)圧縮アルゴリズムの選択: - snappy:
バランスが良く、デフォルト推奨 - zstd:
最高の圧縮率、読み書き速度も良好 - lz4: 最速の圧縮・解凍 -
brotli: 最高の圧縮率だが遅い - uncompressed:
圧縮なし、最速だがファイルサイズ大
行グループサイズ: - 小さい値(10,000-50,000): メモリ効率が良い、フィルタリングに有利 - 大きい値(100,000-500,000): 圧縮率が高い、スキャン性能に有利 - デフォルト(100,000): バランスが良い
# パラメータを変更して再解析
de_params_v2 <- list(
method = "DESeq2",
alpha = 0.01,
lfc_threshold = 1.5
)
ol_save("de_params", de_params_v2)
# 新しいパラメータでDE結果を再計算
de_results_v2 <- data.frame(
gene_id = paste0("GENE", 1:10),
log2FC = rnorm(10, 0, 2.5),
pvalue = runif(10, 0, 0.01),
padj = runif(10, 0, 0.01)
)
ol_save("de_results", de_results_v2,
depends_on = c("normalized_counts", "de_params")
)
# 新バージョンにタグ付け
ol_tag_object("de_results", "strict_analysis")
# 別の解析手法を試す
de_params_edger <- list(
method = "edgeR",
alpha = 0.05,
lfc_threshold = 1.0
)
ol_save("de_params", de_params_edger)
de_results_edger <- data.frame(
gene_id = paste0("GENE", c(1:12, 25:30)),
log2FC = rnorm(18, 0, 2),
pvalue = runif(18, 0, 0.1),
padj = runif(18, 0, 0.1)
)
ol_save("de_results", de_results_edger,
depends_on = c("normalized_counts", "de_params")
)
ol_tag_object("de_results", "edger_analysis")# 全バージョンをリスト表示
versions <- ol_list_object_versions("de_results")
print(versions)
# バージョン間の比較
comparison <- ol_compare_versions("de_results")
print(comparison)
# 特定のタグ間の比較
tag_comparison <- ol_compare_versions("de_results",
versions = c("baseline_analysis", "strict_analysis")
)
print(tag_comparison)出力の見方:
version_ts: バージョンのタイムスタンプtags: そのバージョンに付けられたタグsize_bytes: オブジェクトのサイズ(バイト)dependencies: そのバージョンの依存関係size_change: 前のバージョンからのサイズ変化time_since_previous: 前のバージョンからの経過時間deps_added: 新しく追加された依存関係deps_removed: 削除された依存関係# igraphパッケージが必要
if (requireNamespace("igraph", quietly = TRUE)) {
# 上流の依存関係を可視化
ol_plot_lineage("de_results",
direction = "upstream",
layout = "sugiyama",
main = "DE Results - Upstream Dependencies"
)
# 双方向の依存関係を可視化
ol_plot_lineage("normalized_counts",
direction = "both",
layout = "tree",
main = "Normalized Counts - Full Lineage"
)
}可視化の見方:
# 新しいテーブルを追加
filtered_results <- de_results[de_results$padj < 0.05, ]
ol_write("filtered_de", filtered_results)
# 以前のラベル状態に戻る
ol_checkout("experiment_v1")
# filtered_deテーブルは存在しなくなる
current_tables <- ol_list_tables()
cat(
"Tables after checkout:",
paste(current_tables$table_name, collapse = ", "),
"\n"
)ol_checkout()
は指定したラベル時点の全テーブルとオブジェクトの状態を復元します。
# 再度raw_countsを作成(checkoutで消えた可能性があるため)
ol_write("raw_counts", raw_counts, mode = "overwrite")
# 特定の列のみを選択して読み込み
selected <- ol_fread("raw_counts",
select = c("gene_id", "sample1", "sample2"),
nrows = 10
)
head(selected)
# 条件でフィルタリング
filtered <- ol_fread("raw_counts",
filter = "sample1 > 100"
)
head(filtered)if (requireNamespace("SummarizedExperiment", quietly = TRUE)) {
# ロングフォーマットのデータを作成
long_counts <- data.frame(
feature = rep(paste0("GENE", 1:100), each = 4),
sample = rep(paste0("sample", 1:4), times = 100),
value = rpois(400, 100)
)
ol_write("long_counts", long_counts, mode = "overwrite")
# SummarizedExperimentとして読み込み
se <- ol_read_se("long_counts",
feature_col = "feature",
sample_col = "sample",
value_col = "value",
backing = "memory"
)
print(se)
}if (requireNamespace("MultiAssayExperiment", quietly = TRUE)) {
# 複数のアッセイデータを準備
rna_data <- data.frame(
feature = rep(paste0("GENE", 1:50), each = 4),
sample = rep(paste0("sample", 1:4), times = 50),
value = rpois(200, 100)
)
ol_write("rna_assay", rna_data, mode = "overwrite")
protein_data <- data.frame(
feature = rep(paste0("PROT", 1:30), each = 4),
sample = rep(paste0("sample", 1:4), times = 30),
value = rnorm(120, 50, 10)
)
ol_write("protein_assay", protein_data, mode = "overwrite")
# MultiAssayExperimentとして読み込み
mae <- ol_read_mae(
assays = list(
rna = list(name = "rna_assay"),
protein = list(name = "protein_assay")
),
backing = "memory"
)
print(mae)
}# 1. プロジェクト初期化
ol_init("rnaseq_project")
# 2. 生データの保存
set.seed(456)
raw_data <- data.frame(
gene_id = paste0("GENE", 1:200),
control_1 = rpois(200, 100),
control_2 = rpois(200, 100),
control_3 = rpois(200, 100),
treated_1 = rpois(200, 120),
treated_2 = rpois(200, 120),
treated_3 = rpois(200, 120)
)
ol_write("raw_expression", raw_data)
# 3. QCパラメータの保存
qc_params <- list(
min_counts = 10,
min_samples = 3,
method = "standard"
)
ol_save("qc_parameters", qc_params)
# 4. QC後のデータ
qc_data <- raw_data[rowSums(raw_data[, -1] > 10) >= 3, ]
ol_write(
"qc_filtered",
qc_data,
depends_on = c("raw_expression", "qc_parameters")
)
# 5. 正規化パラメータ
norm_params <- list(
method = "TMM",
log_transform = TRUE
)
ol_save("norm_parameters", norm_params)
# 6. 正規化データ
norm_data <- qc_data
for (i in 2:ncol(norm_data)) {
norm_data[[i]] <- log2(norm_data[[i]] + 1)
}
ol_write("normalized", norm_data,
depends_on = c("qc_filtered", "norm_parameters")
)
# 7. 統計解析パラメータ
stats_params <- list(
test = "t-test",
alpha = 0.05,
correction = "BH"
)
ol_save("stats_parameters", stats_params)
# 8. 統計解析結果
set.seed(789)
de_final <- data.frame(
gene_id = sample(qc_data$gene_id, 30),
log2fc = rnorm(30, 1, 0.5),
pvalue = runif(30, 0, 0.05),
padj = runif(30, 0, 0.05)
)
ol_save("final_de_results", de_final,
depends_on = c("normalized", "stats_parameters")
)
# 9. 解析をコミット
ol_commit(
note = "Complete RNA-seq differential expression analysis",
params = list(
samples = 6,
genes_tested = nrow(qc_data),
significant = nrow(de_final),
date = as.character(Sys.Date())
)
)
# 10. ラベルを作成
ol_label("final_analysis_v1")
# 11. 完全な系統を確認
full_lineage <- ol_show_lineage("final_de_results", direction = "upstream")
print(full_lineage)
# 12. 依存関係を可視化
if (requireNamespace("igraph", quietly = TRUE)) {
ol_plot_lineage("final_de_results",
direction = "upstream",
layout = "sugiyama",
main = "RNA-seq Analysis Pipeline"
)
}ol_init(): プロジェクト初期化ol_label(): プロジェクト全体のラベル付けol_checkout(): ラベル状態への復元ol_write(): テーブルの保存ol_read(): テーブルの読み込みol_save(): Rオブジェクトの保存ol_read_object(): Rオブジェクトの読み込みol_load(): ol_read()のエイリアスol_fread(): フィルタリング付き読み込みol_tag(): テーブルのタグ付けol_tag_object(): オブジェクトのタグ付けol_list_object_versions(): バージョン一覧ol_compare_versions(): バージョン比較ol_commit(): コミットの作成ol_log(): テーブル履歴の表示ol_log_commits(): コミット履歴の表示ol_get_dependencies(): 依存関係の取得ol_show_lineage(): 完全な系統樹の表示ol_plot_lineage(): 依存関係グラフの可視化ol_list_tables(): テーブル一覧ol_list_objects(): オブジェクト一覧ol_list_tags(): タグ一覧ol_list_labels(): ラベル一覧ol_read_se(): SummarizedExperiment作成ol_read_mae(): MultiAssayExperiment作成ol_drop(): テーブル削除depends_on
パラメータを使って解析フローを記録ol_label()ol_commit() に記録ol_plot_lineage() で視覚化ol_compare_versions()