2017-01-26 8 views
3

Ich versuche, Daten für zwei verschiedene Variablen zu sammeln, verteilt auf mehrere Spalten, jeweils gruppiert von zwei anderen Variablen. Hier ist das Problem. Ich habe mehrere Gene, mehrere Proben. Jede Probe hat drei verschiedene mögliche Genotypen mit jeweils einer zugehörigen Häufigkeit. Ich möchte das aufräumen, um eine einzige Spalte für Gen, Probe, Genotyp, Häufigkeit zu bekommen.Gruppierte multicolumn Versammlung mit dplyr, tidyr, purrr

Ich habe eine Hackjob-Lösung, die das Erstellen von Listenspalten, die Verbreitung dieser Spalten und das Extrahieren der Spalten mit purrr :: map-Funktionen beinhaltet. Es ist hässlich, nicht wirklich skalierbar, und die Frequenz wird in ein Zeichen konvertiert, bevor es zurück in numerische konvertiert wird, nicht ideal.

Gibt es einen besseren Weg, um dieses Problem zu lösen?


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

würde ich einfach tun 'Bibliothek (data.table); schmelzen (setDT (have), id = 1: 2, measure = Muster ("Genotyp", "Freq")), aber das wurde nicht von Hadley entwickelt, also kann man es ignorieren. –

+0

@DavidArenburg das funktioniert wunderbar. Überlegen Sie, ob Sie es zu einer offiziellen Antwort machen. –

Antwort

5

Sie to_long() vom sjmisc-package verwenden könnte, die auf einmal mehrere Spalten sammelt:

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() erfordert die Namen der Schlüssel- und Wertespalten, gefolgt von mehreren Spaltennamen pro Vektor, die gesammelt werden sollen.

1

Voll tidyverse Ansatz:

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

Ist * tidyverse * eine Designphilosophie oder ein eingeschränkter Satz von Paketen? – Daniel

+0

Ich würde sagen beide, oder zumindest einen Workflow, der sich darauf konzentriert, lesbaren Code über Pipes zu produzieren und sich auf saubere Daten zu konzentrieren. –

+0

@Daniel Muss mit Jake übereinstimmen - ich würde auch mit beiden auf diesem gehen. Hier ist ein guter Ort, um http://vita.had.co.nz/papers/tidy-data.pdf oder https://vimeo.com/33727555 zu starten, und ein großartiger Ort, um fortzufahren, könnte hier sein: http://r4ds.had.co.nz/ –

Verwandte Themen