tidyverse〜データフレームの各行を個別に処理 rowwise() の使い方

スポンサーリンク

バイオインフォマティクスでは、遺伝子発現データ、配列データ、臨床データなど、膨大な情報を扱うことが求められます。これらのデータを効率よく処理するために R の tidyverse、特に dplyr の活用が重要です。

今回は、dplyr の rowwise() の基本と応用について解説します。rowwise() は、データフレームの各行を個別に処理したいときに役立つ関数です。バイオインフォマティクスにおける具体的な応用例も交えながら、その活用方法を詳しく見ていきましょう。


1. rowwise() の基本

1.1 なぜ rowwise() が必要なのか?

通常、dplyrmutate() は列単位(ベクトル化)で処理を行います。しかし、各行ごとに異なる関数を適用したい場合 には、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() を適切に活用することで、より効率的にデータ解析が行えますよ〜!!

今後のデータ解析にぜひ活用してくださいね〜!

タイトルとURLをコピーしました