如何通过将现有行的值与 R dplyr 组合来向数据框添加行

How to add rows to dataframe by combining values of already existing rows with R dplyr

我有以下table,我想修改:

type position ratio number percentage
DNA intergenic 0.00026933362 225173 40.757876065
DNA intragenic 0.00021799943 41250 7.466536342
LINE intergenic 0.00027633335 48619 8.800376494
LINE intragenic 0.00031015097 9578 1.733684487

我想添加包含以下修改的行:

  1. 类型:如果值“类型”在两行之间相同(在我的情况下总是如此),请将其再次添加到列“类型”的单独行中。

  2. 位置:将值从 intergenic/intragenic 更改为 "genome" if (1)

  3. 比率:比率值将是根据相同类型值的基因间行和基因内行的比率计算的加权平均值:
    ((number_intragenic * ratio_intragenic) + (number_intergenic * ratio_intergenic))/(number_intragenic + number_intergenic)

  4. number:相同类型的数字值之和:sum(number_intergenic + number_intragenic)

  5. 相同类型的百分比值之和:sum(percentage_intergenic + percentage_intragenic)

我的问题是我不知道如何通过对现有行进行特定计算来向数据框添加行。在 dplyr 中使用 mutate 添加列很容易。我如何为行执行此操作?

如果解决方案在 dplyr 中提供,我会更喜欢。

编辑:加权平均值的公式是错误的。我在公式的以下部分添加了一个 + 号而不是 * 号:(number_intergenic + ratio_intergenic)。现在已经修复了。

献给亲爱的@akrun ,是他教会了我如何做到这一点:

library(dplyr)
library(purrr)
library(tibble)

df %>%
  group_split(type) %>%
  map_dfr(~ add_row(.x, type = first(.x$type), position = "genome", 
                    ratio = ((.x$ratio[2]*.x$number[2]) + (.x$ratio[1]+.x$number[1])) / 
                      (.x$number[1]+.x$number[2]), number = .x$number[1] + .x$number[2], 
                    percentage = .x$percentage[1] + .x$percentage[2]))


# A tibble: 6 x 5
  type  position      ratio number percentage
  <chr> <chr>         <dbl>  <int>      <dbl>
1 DNA   intergenic 0.000269 225173      40.8 
2 DNA   intragenic 0.000218  41250       7.47
3 DNA   genome     0.845    266423      48.2 
4 LINE  intergenic 0.000276  48619       8.80
5 LINE  intragenic 0.000310   9578       1.73
6 LINE  genome     0.835     58197      10.5 

这是一个解决方案。

dplyr 并不意味着创建新行,因为结果通常不被认为是“整洁的”。在您的情况下,您想汇总数据(为此我使用了自定义函数)。您可以单独使用摘要,也可以使用 bind_rows() 将其添加到原始 table.

注意,您可能需要检查 number_intragenic 及其朋友的长度是否为 1,这可能会防止一些意外错误,例如 stopifnot(length(number_intragenic)==1.

library(tidyverse)
df = read.table(header=T, text="
type    position    ratio   number  percentage
DNA intergenic  0.00026933362   225173  40.757876065
DNA intragenic  0.00021799943   41250   7.466536342
LINE    intergenic  0.00027633335   48619   8.800376494
LINE    intragenic  0.00031015097   9578    1.733684487
")

get_ratio = function(number, ratio, position){
  number_intragenic = number[position=="intragenic"]
  ratio_intragenic = ratio[position=="intragenic"]
  number_intergenic = number[position=="intergenic"]
  ratio_intergenic = ratio[position=="intergenic"]
  ((number_intragenic * ratio_intragenic) + (number_intergenic + ratio_intergenic))/(number_intragenic+number_intergenic)
}

df_summary = df %>% 
  group_by(type) %>% 
  summarise(ratio=get_ratio(number, ratio, position), 
            number=sum(number), 
            percentage=sum(percentage)) %>% 
  mutate(position="genome", .after="type")

bind_rows(df, df_summary) %>% 
  arrange(type)
#>   type   position        ratio number percentage
#> 1  DNA intergenic 0.0002693336 225173  40.757876
#> 2  DNA intragenic 0.0002179994  41250   7.466536
#> 3  DNA     genome 0.8452047787 266423  48.224412
#> 4 LINE intergenic 0.0002763333  48619   8.800376
#> 5 LINE intragenic 0.0003101510   9578   1.733684
#> 6 LINE     genome 0.8354721189  58197  10.534061

reprex package (v2.0.0)

于 2021-05-12 创建