2017-01-26 9 views
3

2つの異なる変数のデータを、それぞれ複数の列に分散させ、2つの他の変数でグループ化してデータを収集しようとしています。ここに問題がある。私はいくつかの遺伝子、いくつかのサンプルを持っています。各サンプルには3つの異なる可能な遺伝子型があり、それぞれに関連する頻度があります。私は遺伝子、サンプル、遺伝子型、頻度のための単一の列を取得するためにこれを整頓したい。dplyr、tidyr、purrrでグループ化された複数列の集まり

私はリストコラムを作成し、それらを広げ、その後、purrr :: map関数を使ってカラムを抽出するというハックジョップの解決法を持っています。それは実際にスケーラブルではない、醜いですし、周波数は文字に変換されてから理想的ではなく数値に変換されます。

この問題を解決するには、より良い方法がありますか?


library(tidyverse) 
# or, separately load dplyr, tibble, tidyr, purrr 

# Here's what I have 
have <- data_frame(gene=rep(c("gX", "gY"), each=2), 
        sample=rep(c("s1", "s2"), 2), 
        genotype1=c("AA", "AA", "GG", "GG"), 
        genotype2=c("AC", "AC", "GT", "GT"), 
        genotype3=c("CC", "CC", "TT", "TT"), 
        freq1=c(.8,.9, .7, .6), 
        freq2=c(.15,.1, .2, .35), 
        freq3=c(.05,0, .1, .05)) 
have 
#> # A tibble: 4 × 8 
#> gene sample genotype1 genotype2 genotype3 freq1 freq2 freq3 
#> <chr> <chr>  <chr>  <chr>  <chr> <dbl> <dbl> <dbl> 
#> 1 gX  s1  AA  AC  CC 0.8 0.15 0.05 
#> 2 gX  s2  AA  AC  CC 0.9 0.10 0.00 
#> 3 gY  s1  GG  GT  TT 0.7 0.20 0.10 
#> 4 gY  s2  GG  GT  TT 0.6 0.35 0.05 


# Here's what I want. 
# Do a multicolumn gather grouped by gene and sample 
want <- have %>% 
    group_by(gene, sample) %>% 
    summarize(x1=list(c(genotype=genotype1, freq=freq1)), 
      x2=list(c(genotype=genotype2, freq=freq2)), 
      x3=list(c(genotype=genotype3, freq=freq3))) %>% 
    ungroup() %>% 
    gather(key, value, x1, x2, x3) %>% 
    mutate(genotype=map_chr(value, "genotype"), 
     freq=map_chr(value, "freq") %>% as.numeric) %>% 
    select(-key, -value) %>% 
    arrange(gene, sample, genotype) 
want 
#> # A tibble: 12 × 4 
#>  gene sample genotype freq 
#> <chr> <chr> <chr> <dbl> 
#> 1  gX  s1  AA 0.80 
#> 2  gX  s1  AC 0.15 
#> 3  gX  s1  CC 0.05 
#> 4  gX  s2  AA 0.90 
#> 5  gX  s2  AC 0.10 
#> 6  gX  s2  CC 0.00 
#> 7  gY  s1  GG 0.70 
#> 8  gY  s1  GT 0.20 
#> 9  gY  s1  TT 0.10 
#> 10 gY  s2  GG 0.60 
#> 11 gY  s2  GT 0.35 
#> 12 gY  s2  TT 0.05 
+5

私は単にライブラリ(data.table) 'だろう。それはHadleyによって開発されたものではないので、無視しても問題ありません。 –

+0

@DavidArenburgこれは美しく動作します。正式な回答にすることを検討してください。 –

答えて

5

あなたが一度に複数の列を収集しsjmisc-packageからto_long()を使用することができます。

to_long(have, keys = "genos", values = c("genotype", "freq"), 
     c("genotype1", "genotype2", "genotype3"), 
     c("freq1", "freq2", "freq3")) 

## A tibble: 12 × 5 
##  gene sample  genos genotype freq 
## <chr> <chr>  <chr> <chr> <dbl> 
## 1  gX  s1 genotype1  AA 0.80 
## 2  gX  s2 genotype1  AA 0.90 
## 3  gY  s1 genotype1  GG 0.70 
## 4  gY  s2 genotype1  GG 0.60 
## 5  gX  s1 genotype2  AC 0.15 
## 6  gX  s2 genotype2  AC 0.10 
## 7  gY  s1 genotype2  GT 0.20 
## 8  gY  s2 genotype2  GT 0.35 
## 9  gX  s1 genotype3  CC 0.05 
## 10 gX  s2 genotype3  CC 0.00 
## 11 gY  s1 genotype3  TT 0.10 
## 12 gY  s2 genotype3  TT 0.05 

to_long()には、キー列と値列の名前と、収集するベクトルごとに複数の列名が必要です。

1

tidyverseアプローチ:

want <- have %>% 
    gather(variable, value, -gene, -sample) %>% 
    mutate(group = parse_number(variable), 
      variable = str_extract(variable,"\\D+")) %>% 
    spread(variable, value) %>% 
    select(-group) 
+0

* tidyverse *はデザイン哲学か制限付きパッケージのセットですか? – Daniel

+0

私はどちらも、少なくともパイプラインで読みやすいコードを生成し、整頓されたデータに焦点を合わせることに重点を置くワークフローと言います。 –

+0

@Daniel Jakeと同意する必要があります - 私はまたこの両方で行くでしょう。 http://vita.had.co.nz/papers/tidy-data.pdfやhttps://vimeo.com/33727555を開始するのに適しています。今後も継続するにはここをクリックしてください:http:///r4ds.had.co.nz/ –

関連する問題