R (tidyverse), group_by, top_n グループごとの上位を求める

group_by() 関数と top_n() 関数を組み合わせることで、グループごとの上位を求めることができます。

例えば、下記のように同じ Symbol を持つグループのデータがあったとします。

> result_data
# A tibble: 9 x 5
  Id    Symbol Sample1 Sample2 Ratio
  <chr> <chr>    <dbl>   <dbl> <dbl>
1 id1   AAA          1       4  4
2 id2   AAA          2       5  2.5
3 id3   AAA          3       6  2
4 id4   BBB          4       1  0.25
5 id5   BBB          5       2  0.4
6 id6   BBB          6       3  0.5
7 id7   CCC          3       4  1.33
8 id8   CCC          2       5  2.5
9 id9   DDD          1       6  6

この時、各シンボルごとに1番 Ratio の高いデータだけを選ぶには、 group_by(Symbol) として、グループ化したのち、 top_n(1, Ratio) を適応すれば良いです。

実行結果は、下記のようになります。

> result_data %>% group_by(Symbol) %>% top_n(1, Ratio)
# A tibble: 4 x 5
# Groups:   Symbol [4]
  Id    Symbol Sample1 Sample2 Ratio
  <chr> <chr>    <dbl>   <dbl> <dbl>
1 id1   AAA          1       4   4
2 id6   BBB          6       3   0.5
3 id8   CCC          2       5   2.5
4 id9   DDD          1       6   6

 

R (tidyverse), top_n() 上位を抽出

テーブルから、ある列の上位を抽出するには、 top_n() 関数を使います。

top_n(上位いくつまで, 対象の列)

ratio を計算して、上位2つを表示した例です。

top2 <- result_data %>%
  mutate("Ratio" = Sample2 / Sample1) %>%
  top_n(2, Ratio)

> top2
# A tibble: 2 x 6
  Id    Symbol Description   Sample1 Sample2 Ratio
  <chr> <chr>  <chr>           <dbl>   <dbl> <dbl>
1 id1   AAA    lorem ipsum a       1       4   4
2 id2   BBB    lorem ipsum b       2       5   2.5

逆に、下位を求める場合は、順位にマイナス(-)を付けます。

bottom2 <- result_data %>%
  mutate("Ratio" = Sample2 / Sample1) %>%
  top_n(-2, Ratio)

> bottom2
# A tibble: 2 x 6
  Id    Symbol Description   Sample1 Sample2 Ratio
  <chr> <chr>  <chr>           <dbl>   <dbl> <dbl>
1 id2   BBB    lorem ipsum b       2       5   2.5
2 id3   CCC    lorem ipsum c       3       6   2
 

R (tidyverse), mutate 列を変更、修正(上書き)

mutate() 関数を使って、列に変更を加える場合、同じ列名を指定することで、列の内容を上書きすることもできます。下記の例では、 str_to_lower() 関数を使って、全て小文字の Symbol に変換して、元の Symbol 列に格納しています。

> result_data
# A tibble: 3 x 5
  Id    Symbol Description   Sample1 Sample2
  <chr> <chr>  <chr>           <dbl>   <dbl>
1 id1   AAA    lorem ipsum a       1       4
2 id2   BBB    lorem ipsum b       2       5
3 id3   CCC    lorem ipsum c       3       6
>
>
> result_data %>% mutate(Symbol = str_to_lower(Symbol))
# A tibble: 3 x 5
  Id    Symbol Description   Sample1 Sample2
  <chr> <chr>  <chr>           <dbl>   <dbl>
1 id1   aaa    lorem ipsum a       1       4
2 id2   bbb    lorem ipsum b       2       5
3 id3   ccc    lorem ipsum c       3       6

この場合は、新たに列が追加されることはありません。

stringr パッケージ

文字列の操作に便利な関数は、 stringr パッケージに含まれています。(tidyverse パッケージの一部であるため、tidyverse パッケージを読み込むと、 stringr パッケージも使える状態になります。)置換や、連結、また、正規表現も使えます。

検出 (str_detect), 置換 (str_replace), 連結 (str_c), 大文字に変換(str_to_upper), 小文字に変換 (str_to_lower), 先頭だけ大文字 (str_to_title)

https://stringr.tidyverse.org

 

R (tidyverse), mutate 列を変更、追加

読み込んだデータに対して、演算した結果を格納したり、新たな列(データ)を追加するには、 mutate() 関数を使います。

テーブル %>% mutate(追加される列名 = 演算の式)

例えば、2つの列の結果から、ratio を算出して、その結果を格納する場合に使います。下記の例では、 Sample2 と Sample1 の列から ratio を求め、その結果を「Ratio」列に格納しています。新たに追加される列であるため、列名の Ratio をダブルクオーテーションで囲みます。

> raw_data
# A tibble: 3 x 5
  Id    Symbol Description   Sample1 Sample2
  <chr> <chr>  <chr>           <dbl>   <dbl>
1 id1   AAA    lorem ipsum a       1       4
2 id2   BBB    lorem ipsum b       2       5
3 id3   CCC    lorem ipsum c       3       6
>
>
> raw_data %>% mutate("Ratio" = Sample2 / Sample1)
# A tibble: 3 x 6
  Id    Symbol Description   Sample1 Sample2 Ratio
  <chr> <chr>  <chr>           <dbl>   <dbl> <dbl>
1 id1   AAA    lorem ipsum a       1       4   4
2 id2   BBB    lorem ipsum b       2       5   2.5
3 id3   CCC    lorem ipsum c       3       6   2

演算の式 (Sample2 / Sample1 ) が、それぞれの「行」に対して、適用されるようなイメージです。式には、関数も使えます。例えば、平均値を算出するには、 rowMeans() が使えます。

> samples <- raw_data %>% select(starts_with("Sample"))
> samples
# A tibble: 3 x 2
  Sample1 Sample2
    <dbl>   <dbl>
1       1       4
2       2       5
3       3       6
> # 数値だけのオブジェクトを準備
>
> raw_data %>% mutate("Ave" = rowMeans(samples))
# A tibble: 3 x 6
  Id    Symbol Description   Sample1 Sample2   Ave
  <chr> <chr>  <chr>           <dbl>   <dbl> <dbl>
1 id1   AAA    lorem ipsum a       1       4   2.5
2 id2   BBB    lorem ipsum b       2       5   3.5
3 id3   CCC    lorem ipsum c       3       6   4.5

計算の邪魔になるため、 Id などを除いた数値だけのオブジェクト (samples) を作成しておき、 これを rowMeans の引数としています。このパターンで記述しておくと、サンプル数が多くても、同じ表現で計算できます。

もちろん、パイプで連続した処理も可能です。

up_genes <- raw_data %>%
              mutate("Ratio" = Sample2 / Sample1) %>%
              mutate("Ave" = rowMeans(samples))   %>%
              select(Symbol, Ratio, Ave)          %>%
              filter(Ratio > 2)

> # 上記の実行結果
> up_genes
# A tibble: 2 x 3
  Symbol Ratio   Ave
  <chr>  <dbl> <dbl>
1 AAA      4     2.5
2 BBB      2.5   3.5
 

R (tidyverse), select で除外する

select() 関数では、抽出する列を選択できますが、特定の列を除外するということもできます。使い方は、 select(-列名) と、列名にマイナスを付けるだけです。

> result_data
# A tibble: 3 x 5
  Id    Symbol Description   Sample1 Sample2
  <chr> <chr>  <chr>           <dbl>   <dbl>
1 id1   AAA    lorem ipsum a       1       4
2 id2   BBB    lorem ipsum b       2       5
3 id3   CCC    lorem ipsum c       3       6
>
>
> result_data %>% select(-Id, -Symbol, -Description)
# A tibble: 3 x 2
  Sample1 Sample2
    <dbl>   <dbl>
1       1       4
2       2       5
3       3       6

上記の例では、Id, Symbol, Description を取り除いて、データだけのオブジェクトを表示させています。抽出するサンプルが多い時は、全ての列の名前を記述するのが大変になります。その場合は、除外する列だけ、名前を書く方と便利です。

従来の R のように、 列の番号を指定して除外することも可能ですが、可読性という意味では、明示的に列名を指定する方が良いでしょう。

> result_data[, c(-1:-3)]
# A tibble: 3 x 2
  Sample1 Sample2
    <dbl>   <dbl>
1       1       4
2       2       5
3       3       6