【问题标题】:Grouped multicolumn gather with dplyr, tidyr, purrr [duplicate]使用 dplyr、tidyr、purrr 分组多列聚集 [重复]
【发布时间】:2017-06-12 08:34:27
【问题描述】:

我正在尝试收集分布在多个列中的两个不同变量的数据,这些变量由另外两个变量分组。这就是问题所在。我有几个基因,几个样本。每个样本具有三种不同的可能基因型,每种都有相关的频率。我想整理一下,以获得基因、样本、基因型、频率的单列。

我对此有一个 hackjob 解决方案,其中包括创建列表列、传播这些列,然后使用 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

【问题讨论】:

  • 我会简单地做library(data.table) ; melt(setDT(have), id = 1:2, measure = patterns("genotype", "freq")),但这不是由 Hadley 开发的,所以你可以放心地忽略。
  • @DavidArenburg 这很好用。考虑将其作为官方答案。

标签: r dplyr tidyr purrr tidyverse


【解决方案1】:

您可以使用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() 需要键列和值列的名称,后跟应收集的每个向量的多个列名称。

【讨论】:

    【解决方案2】:

    完整的tidyverse 方法:

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

    【讨论】:

    • tidyverse 是一种设计理念还是一组受限的软件包?
    • 我会说两者,或者至少是一个专注于通过管道生成可读代码并专注于整洁数据的工作流。
    • @Daniel 必须同意杰克的观点——我也会同意这两个观点。这是一个开始vita.had.co.nz/papers/tidy-data.pdfvimeo.com/33727555 的好地方,可以在这里继续一个好地方:r4ds.had.co.nz
    • 是的,我知道这些资源。我个人认为 tidyverse 更像是一种哲学(另见github.com/tidyverse/tidyverse/blob/master/vignettes/…),与特定作者(在这种情况下为哈德利)无关。 to_long()-function 遵循与tidyr::gather() 相同的设计原则,那么为什么这不适合“tidyverse 方法”呢?我认为我的观点与@David-Arenburg 提到的相同:“它不是由 Hadley 开发的,所以你可以放心地忽略”。 ;-)
    • 有些人喜欢多合一的方法,它限制了他们必须学习的部分和包的数量。 to_long() 绝对适合整洁的数据工具和理念。我的回答仅限于使用 tidyverse 包集合,而不是引发愚蠢的包/作者讨论
    猜你喜欢
    • 2017-03-21
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 2015-08-16
    • 1970-01-01
    相关资源
    最近更新 更多