web-dev-qa-db-fra.com

Ajouter une ligne dans chaque groupe à l'aide de dplyr et add_row ()

Si j'ajoute une nouvelle ligne au ìris ensemble de données avec:

iris <- as_tibble(iris)

> iris %>% 
    add_row(.before=0)

# A tibble: 151 × 5
    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl>   <chr>
1            NA          NA           NA          NA    <NA> <--- Good!
2           5.1         3.5          1.4         0.2  setosa
3           4.9         3.0          1.4         0.2  setosa

Ça marche. Alors, pourquoi ne puis-je pas ajouter une nouvelle ligne au-dessus de chaque "sous-ensemble" avec:

iris %>% 
 group_by(Species) %>% 
 add_row(.before=0)

Error: is.data.frame(df) is not TRUE
14
Dan

Si vous souhaitez utiliser une opération groupée, vous avez besoin de do comme JasonWang décrit dans son commentaire, car d'autres fonctions comme mutate ou summarise attendent un résultat avec le même nombre de lignes comme trame de données groupée (dans votre cas, 50) ou avec une seule ligne (par exemple lors du résumé).

Comme vous le savez probablement, en général, do peut être lent et devrait être un dernier recours si vous ne pouvez pas obtenir votre résultat d'une autre manière. Votre tâche est assez simple car elle implique uniquement l'ajout de lignes supplémentaires dans votre bloc de données, ce qui peut être effectué par une simple indexation, par exemple regardez la sortie de iris[NA, ].

Ce que vous voulez, c'est essentiellement créer un vecteur

indices <- c(NA, 1:50, NA, 51:100, NA, 101:150)

(puisque le premier groupe est dans les rangées 1 à 50, le second dans 51 à 100 et le troisième dans 101 à 150).

Le résultat est alors iris[indices, ].

Une manière plus générale de construire ce vecteur utilise group_indices.

indices <- seq(nrow(iris)) %>% 
    split(group_indices(iris, Species)) %>% 
    map(~c(NA, .x)) %>%
    unlist

(map vient de purrr que je suppose que vous avez chargé car vous l'avez tagué avec tidyverse).

16
konvas