バイオインフォマティクスでは、遺伝子発現データ、配列データ、臨床データなど、膨大な情報を扱うことが求められます。これらのデータを効率よく処理するために R の tidyverse、特に dplyr
の活用が重要です。
今回は、dplyr の rowwise()
の基本と応用について解説します。rowwise()
は、データフレームの各行を個別に処理したいときに役立つ関数です。バイオインフォマティクスにおける具体的な応用例も交えながら、その活用方法を詳しく見ていきましょう。
1. rowwise() の基本
1.1 なぜ rowwise() が必要なのか?
通常、dplyr
の mutate()
は列単位(ベクトル化)で処理を行います。しかし、各行ごとに異なる関数を適用したい場合 には、rowwise()
が必要です。
例えば、次のようなデータフレームを考えます。
library(dplyr)
df <- tibble(
sample_id = c("S1", "S2", "S3"),
gene1 = c(10, 20, 30),
gene2 = c(5, 15, 25),
gene3 = c(2, 8, 12)
)
df
# A tibble: 3 × 4
sample_id gene1 gene2 gene3
<chr> <dbl> <dbl> <dbl>
1 S1 10 5 2
2 S2 20 15 8
3 S3 30 25 12
このデータの各行に対して、gene1
から gene3
の 平均値 を計算するとしましょう。
1.2 rowwise() の使い方
通常、mutate()
だけでは行ごとの計算ができません。そこで rowwise()
を使います。
df %>%
rowwise() %>%
mutate(gene_avg = mean(c(gene1, gene2, gene3)))
# A tibble: 3 × 5
# Rowwise:
sample_id gene1 gene2 gene3 gene_avg
<chr> <dbl> <dbl> <dbl> <dbl>
1 S1 10 5 2 5.67
2 S2 20 15 8 14.33
3 S3 30 25 12 22.33
ここでは、各行ごとに mean()
を適用し、gene_avg
列に格納しています。
1.3 rowwise() の解除
データフレームは rowwise()
を適用した後も「rowwise オブジェクト」のままです。そのため、通常の tibble に戻すには ungroup()
を使います。
df %>%
rowwise() %>%
mutate(gene_avg = mean(c(gene1, gene2, gene3))) %>%
ungroup()
ungroup()
しないと、後続の処理が遅くなる可能性があるため、特に大規模データを扱う場合は注意が必要です。
2. rowwise() の応用
rowwise()
は、バイオインフォマティクスでのデータ解析に役立ちます。いくつかの応用例を紹介します。
2.1 ゲノムデータの変換:GC 含量の計算
DNA 配列の GC 含量(G と C の割合)を求めたい場合、行ごとに異なる DNA 配列に gc_content()
関数を適用する必要があります。
df_dna <- tibble(
sample_id = c("S1", "S2", "S3"),
sequence = c("ATGCGT", "CCGTTGAA", "GGGATC")
)
gc_content <- function(seq) {
gc_count <- sum(str_count(seq, c("G", "C")))
return(gc_count / nchar(seq))
}
df_dna %>%
rowwise() %>%
mutate(gc_ratio = gc_content(sequence))
2.2 RNA-Seq データの正規化
RNA-Seq データでは、各サンプルごとの FPKM/RPKM/TPM の正規化が必要です。各行の発現値をライブラリサイズで割るときにも rowwise()
を使えます。
df_rna <- tibble(
sample_id = c("S1", "S2", "S3"),
gene_counts = c(1000, 5000, 2000),
library_size = c(100000, 200000, 150000)
)
df_rna %>%
rowwise() %>%
mutate(TPM = (gene_counts / library_size) * 1e6)
2.3 各行ごとに異なる関数を適用
バイオデータでは、サンプルごとに異なる計算が必要な場合があります。例えば、異なる閾値で遺伝子発現の log2 変換 を行う場合です。
df_log <- tibble(
sample_id = c("S1", "S2", "S3"),
gene_counts = c(100, 200, 500),
threshold = c(1, 10, 50)
)
df_log %>%
rowwise() %>%
mutate(log_expression = log2(gene_counts + threshold))
3. rowwise() を使わずに同じ処理をする方法
rowwise()
は便利ですが、計算速度が遅くなることがあります。特に大量データを扱う場合は、apply()
や pmap()
などを使う方が効率的なこともあります。
3.1 apply() を使う
行単位の計算には apply()
も利用できます。
df$gene_avg <- apply(df[,2:4], 1, mean)
これは rowwise()
より高速な場合が多いです。
3.2 pmap() を使う
purrr::pmap()
も行ごとの処理に適しています。
df %>%
mutate(gene_avg = pmap_dbl(select(., gene1:gene3), ~ mean(c(...), na.rm = TRUE)))
rowwise()
に比べて処理が速い場合があり、特に数十万行以上のデータを扱う場合に有効です。
4. まとめ
rowwise()
は 各行ごとに異なる関数を適用 するときに便利。ungroup()
を忘れないように注意。- ゲノムデータの変換、RNA-Seq の正規化、サンプルごとの異なる関数適用などで活躍。
- 大規模データでは
apply()
やpmap()
の方が効率的な場合がある。
バイオインフォマティクスでは、多くのケースでデータの行ごとの処理が求められます。rowwise()
を適切に活用することで、より効率的にデータ解析が行えますよ〜!!
今後のデータ解析にぜひ活用してくださいね〜!