2 votes

Comment ajouter des lignes au tableau de données en combinant les valeurs des lignes déjà existantes avec R dplyr

Je ai le tableau suivant, que je voudrais modifier:

type

position

ratio

number

percentage

DNA

intergénique

0.00026933362

225173

40.757876065

DNA

intragénique

0.00021799943

41250

7.466536342

LIGNE

intergénique

0.00027633335

48619

8.800376494

LIGNE

intragénique

0.00031015097

9578

1.733684487

Je veux ajouter des lignes qui contiennent les modifications suivantes:

  1. type: si la valeur "type" est identique entre deux lignes (ce qui est toujours le cas dans mon cas), ajoutez-la à nouveau dans une ligne séparée de la colonne "type".

  2. position: changer la valeur de intergénique/intragénique à "génome" si (1)

  3. ratio: la valeur du ratio serait la moyenne pondérée calculée à partir du ratio des lignes intergénique et intragénique de la même valeur de type:
    ((number_intragenic * ratio_intragenic) + (number_intergénique * ratio_intergénique))/(number_intragenic + number_intergénique)

  4. nombre: somme des valeurs de nombre pour le même type: somme(nombre_intergénique + nombre_intragénique)

  5. somme des valeurs de pourcentage pour le même type: somme(percentage_intergénique + percentage_intragenique)

Mon problème est que je ne sais pas comment ajouter des lignes au tableau en faisant des calculs spécifiques à partir des lignes déjà existantes. Il est facile d'ajouter des colonnes en utilisant mutate dans dplyr. Comment puis-je faire cela pour les lignes?

Je préférerais beaucoup que la solution soit fournie dans dplyr.

Modifier: La formule de la moyenne pondérée était incorrecte. J'avais ajouté un signe + au lieu d'un signe * dans la partie suivante de la formule: (nombre_intergénique + ratio_intergénique). Il a maintenant été corrigé.

2voto

Anoushiravan R Points 4928

Dédié à cher @akrun qui m'a enseigné comment faire cela :

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

df %>%
  group_split(type) %>%
  map_dfr(~ add_row(.x, type = first(.x$type), position = "génome", 
                    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], 
                    pourcentage = .x$percentage[1] + .x$percentage[2]))

# Un tibble : 6 x 5
  type  position      ratio number percentage

1 DNA   intergénique 0.000269 225173      40.8 
2 DNA   intragénique 0.000218  41250       7.47
3 DNA   génome       0.845    266423      48.2 
4 LINE  intergénique 0.000276  48619       8.80
5 LINE  intragénique 0.000310   9578       1.73
6 LINE  génome       0.835     58197      10.5

1voto

Dan Chaltiel Points 1462

Voici une solution.

dplyr n'est pas destiné à créer de nouvelles lignes car le résultat n'est souvent pas considéré comme "propre". Dans votre cas, vous souhaitez résumer les données (j'ai utilisé une fonction personnalisée à cette fin). Vous pouvez utiliser le résumé seul ou vous pouvez utiliser bind_rows() pour l'ajouter au tableau d'origine.

À noter, vous voudrez peut-être vérifier que number_intragenic et ses homologues ont une longueur de 1, cela peut éviter certaines erreurs inattendues, par exemple avec stopifnot(length(number_intragenic)==1.

library(tidyverse)
df = read.table(header=T, text="
type    position    ratio   number  percentage
DNA intergénique  0.00026933362   225173  40.757876065
DNA intragénique  0.00021799943   41250   7.466536342
LINE    intergénique  0.00027633335   48619   8.800376494
LINE    intragénique  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 intergénique 0.0002693336 225173  40.757876
#> 2  DNA intragénique 0.0002179994  41250   7.466536
#> 3  DNA     genome 0.8452047787 266423  48.224412
#> 4 LINE intergénique 0.0002763333  48619   8.800376
#> 5 LINE intragénique 0.0003101510   9578   1.733684
#> 6 LINE     genome 0.8354721189  58197  10.534061

Créé le 2021-05-12 par le package reprex (v2.0.0)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X