R tidyverse:複数の列に対して一括で操作「across()」 の使い方

スポンサーリンク

バイオインフォマティクスでは、大量のデータを効率的に処理し、解析することが求められます。R の tidyverse パッケージは、そのようなデータ処理に非常に有用なツールを提供しています。本記事では、dplyr::across() に焦点を当て、その基本から応用までを解説します。


1. across() とは?

1.1 across() の概要

across() は、dplyr 1.0.0 で導入された関数で、複数の列に対して一括で操作を適用できる機能を持っています。従来の mutate()summarise() で列ごとに関数を適用する際のコードを簡潔に記述できるため、特に大規模データ処理での利便性が向上しました。

1.2 基本的な使い方

across()mutate()summarise() の中で使用され、複数の列に対して同じ関数を適用することができます。

library(tidyverse)

# サンプルデータ
df <- tibble(
  sample_id = c("S1", "S2", "S3"),
  gene_A = c(10, 15, 20),
  gene_B = c(5, 10, 15),
  gene_C = c(3, 6, 9)
)

# すべての数値列を2倍にする
df %>%
  mutate(across(where(is.numeric), ~ . * 2))

出力:

# A tibble: 3 × 4
  sample_id gene_A gene_B gene_C
  <chr>      <dbl>  <dbl>  <dbl>
1 S1           20     10      6
2 S2           30     20     12
3 S3           40     30     18

ここでは where(is.numeric) を使って、数値列に限定して * 2 の計算を適用しました。


2. across() の応用

2.1 特定の列のみを選択

バイオインフォマティクスのデータでは、特定の遺伝子の発現データのみ処理することが多くあります。特定の列を選択する場合、c() を使用できます。

df %>%
  mutate(across(c(gene_A, gene_B), log2))

出力:

# A tibble: 3 × 4
  sample_id gene_A gene_B gene_C
  <chr>      <dbl>  <dbl>  <dbl>
1 S1        3.32    2.32       3
2 S2        3.91    3.32       6
3 S3        4.32    3.91       9

ここでは gene_Agene_B のみを選択し、それぞれ対数変換 (log2()) を適用しました。


2.2 複数の関数を適用

複数の関数を適用する場合、リスト list() を使うと、異なる統計量をまとめて計算できます。

df %>%
  summarise(across(c(gene_A, gene_B), list(mean = mean, sd = sd)))

出力:

# A tibble: 1 × 4
  gene_A_mean gene_A_sd gene_B_mean gene_B_sd
       <dbl>     <dbl>      <dbl>    <dbl>
1       15       5.00       10       5.00

このように mean()sd() を適用することで、各遺伝子の平均値と標準偏差を計算できます。


2.3 条件付きで処理

特定の条件を満たす列だけを選択し、異なる操作を適用することも可能です。

df %>%
  mutate(across(where(~ is.numeric(.) && mean(., na.rm = TRUE) > 10), log2))

この例では、平均値が10を超える列のみ log2() を適用します。


3. バイオインフォマティクスでの実用例

3.1 正規化(Zスコア変換)

RNA-seq の発現データを正規化する際には、各遺伝子の Z スコアを計算することが一般的です。

df %>%
  mutate(across(where(is.numeric), ~ (. - mean(.)) / sd(.)))

このコードでは、全数値列に対して (値 - 平均) / 標準偏差 を計算し、正規化します。


3.2 フィルタリング

発現値が一定のしきい値を超える遺伝子のみを保持する場合、filter() の中で across() を使うことができます。

df %>%
  filter(across(c(gene_A, gene_B), ~ . > 10, .names = "keep_{.col}"))

このコードは、gene_A または gene_B が 10 を超える行のみを抽出します。


3.3 複数の処理を同時適用

異なる処理を組み合わせることで、より柔軟なデータ処理が可能になります。

df %>%
  mutate(across(c(gene_A, gene_B), list(log = log2, scale = ~ (. - mean(.)) / sd(.))))

出力:

# A tibble: 3 × 6
  sample_id gene_A_log gene_A_scale gene_B_log gene_B_scale gene_C
  <chr>        <dbl>       <dbl>       <dbl>       <dbl>   <dbl>
1 S1          3.32        -1.22       2.32        -1.22       3
2 S2          3.91         0          3.32         0          6
3 S3          4.32         1.22       3.91         1.22       9

このように、log2 変換と Z スコア変換を同時に適用することも可能です。


4. まとめ

across() を活用することで、tidyverse を使ったデータ処理がより効率的になります。特にバイオインフォマティクスのように多変量データを扱う場面では、以下のような利点があります。

コードが簡潔になる:従来の mutate_at()summarise_at() よりも可読性が向上。
複数の列を一括処理:データセット全体の処理が容易になる。
関数の適用を柔軟に制御:条件に応じた処理や、異なる処理の同時適用が可能。

バイオインフォマティクスにおけるデータ解析では、データの前処理やフィルタリング、正規化などが頻繁に求められます!!

across() をうまく活用して、効率的にデータを処理していきましょう〜!

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