2 votes

La cartographie purrr ne produit pas de données ordonnées

Grâce à ce site, j'utilise la méthode R purrr pour agréger des données en fonction de plusieurs colonnes. L'agrégation fonctionne comme je le souhaite mais la sortie ne fonctionne pas. Voici un exemple utilisant le paquet mtcars jeu de données.

library(dplyr)
library(purrr)
#pull in data
data <- mtcars
#get colnames
variable1 <- colnames(data)
#map the variables
t1 <- map(variable1, ~ data %>%
         group_by_at(.x) %>%
         summarize(number = mean(mpg))) %>%
    set_names(variable1) %>%
    bind_rows(., .id = 'variable')

Là où je m'attendais à trois colonnes (variable prédictive, niveaux dans chacune de ces variables, agrégation), j'en ai 8. Voir l'image ci-dessous :

Output of above code

Comment puis-je prendre mon code en haut et obtenir un ensemble de données bien ordonné ?

3voto

alistaire Points 5898

Une façon simple de le faire est de remodeler vos données en forme longue, ce qui vous permet d'agréger avec dplyr ordinaire :

library(tidyverse)

mpg_means <- mtcars %>% 
    gather(variable, value, -mpg) %>% 
    group_by(variable, value) %>% 
    summarise(mean_mpg = mean(mpg))

mpg_means
#> # A tibble: 146 x 3
#> # Groups:   variable [?]
#>    variable value mean_mpg
#>    <chr>    <dbl>    <dbl>
#>  1 am          0.     17.1
#>  2 am          1.     24.4
#>  3 carb        1.     25.3
#>  4 carb        2.     22.4
#>  5 carb        3.     16.3
#>  6 carb        4.     15.8
#>  7 carb        6.     19.7
#>  8 carb        8.     15.0
#>  9 cyl         4.     26.7
#> 10 cyl         6.     19.7
#> # ... with 136 more rows

Notez que si mtcars est entièrement numérique, si vous avez différents types, la conversion en forme longue contraindra les types variables. Les calculs seront les mêmes, mais cela peut poser des problèmes par la suite. Pour résoudre ce problème, utilisez un format de sortie qui peut gérer différents types, par exemple

mpg_means_in_list_cols <- mtcars %>% 
    as_tibble() %>%    # compact printing for list columns
    summarise_all(list) %>%    # collapse each column into a list of itself
    gather(group, group_values, -mpg) %>% 
    mutate(mpg_means = map2(mpg, group_values,    # for each mpg/value pair, ...
                            ~tibble(mpg = .x, group_value = .y) %>%    # ...reconstruct a data frame...
                                group_by(group_value) %>% 
                                summarise(mean_mpg = mean(mpg))))    # ...and aggregate

mpg_means_in_list_cols
#> # A tibble: 10 x 4
#>    mpg        group group_values mpg_means        
#>    <list>     <chr> <list>       <list>           
#>  1 <dbl [32]> cyl   <dbl [32]>   <tibble [3 × 2]> 
#>  2 <dbl [32]> disp  <dbl [32]>   <tibble [27 × 2]>
#>  3 <dbl [32]> hp    <dbl [32]>   <tibble [22 × 2]>
#>  4 <dbl [32]> drat  <dbl [32]>   <tibble [22 × 2]>
#>  5 <dbl [32]> wt    <dbl [32]>   <tibble [29 × 2]>
#>  6 <dbl [32]> qsec  <dbl [32]>   <tibble [30 × 2]>
#>  7 <dbl [32]> vs    <dbl [32]>   <tibble [2 × 2]> 
#>  8 <dbl [32]> am    <dbl [32]>   <tibble [2 × 2]> 
#>  9 <dbl [32]> gear  <dbl [32]>   <tibble [3 × 2]> 
#> 10 <dbl [32]> carb  <dbl [32]>   <tibble [6 × 2]>

Bien que ce soit décidément moins joli, il est capable de contenir de nombreux types de manière ordonnée. Pour extraire le résultat ci-dessus, il suffit d'ajouter %>% unnest(mpg_means) . En l'état actuel, les variables de regroupement sont chacune contenues dans un élément de liste de group_values et sous forme agrégée dans la première colonne de chaque mpg_means de l'argent.

2voto

Mikko Marttila Points 3262

Lorsque vous regroupez vos données dans le map vous pouvez renommer la variable de regroupement en "level" puisque ces valeurs formeront la colonne contenant les niveaux de la variable de regroupement dans l'ensemble de données final.

Lorsque vous avez des types mixtes de variables de regroupement (par exemple, à la fois numériques et en caractères), vous devrez également convertir la variable de regroupement en caractères afin de pouvoir lier les résultats ensemble.

Avec ces ajouts, vous devriez obtenir ce que vous attendez. (Vous pouvez également sauter le bind_rows en utilisant map_df au lieu de map pour économiser un peu de code, comme je l'ai fait ci-dessous).

reprex::reprex_info()
#> Created by the reprex package v0.1.1.9000 on 2018-02-09

library(purrr)
library(dplyr)

data <- iris
vars <- names(data)

set_names(vars) %>% 
  map_df(function(var) {
    var <- set_names(var, "level")
    data %>% 
      group_by_at(var) %>% 
      summarize_at("Sepal.Length", "mean") %>% 
      mutate_at("level", as.character)
  }, .id = "variable")
#> # A tibble: 126 x 3
#>        variable level Sepal.Length
#>           <chr> <chr>        <dbl>
#>  1 Sepal.Length   4.3          4.3
#>  2 Sepal.Length   4.4          4.4
#>  3 Sepal.Length   4.5          4.5
#>  4 Sepal.Length   4.6          4.6
#>  5 Sepal.Length   4.7          4.7
#>  6 Sepal.Length   4.8          4.8
#>  7 Sepal.Length   4.9          4.9
#>  8 Sepal.Length     5          5.0
#>  9 Sepal.Length   5.1          5.1
#> 10 Sepal.Length   5.2          5.2
#> # ... with 116 more rows

Vous pourriez également envelopper le processus dans une fonction, et permettre à plusieurs variables de se résumer avec plusieurs fonctions. Il faudrait prendre le temps de trouver un nom évocateur (j'ai triché en utilisant simplement foo ici).

foo <- function(data, vars, funs) {
  grps <- names(data)
  set_names(grps) %>% 
    map_df(function(grp) {
      grp <- set_names(grp, "level")
      data %>% 
        group_by_at(grp) %>% 
        summarize_at(vars, funs) %>% 
        mutate_at("level", as.character)
    }, .id = "variable")
}

foo(iris, vars(Sepal.Length, Sepal.Width), funs(mean, sd))
#> # A tibble: 126 x 6
#>        variable level Sepal.Length_mean Sepal.Width_mean Sepal.Length_sd
#>           <chr> <chr>             <dbl>            <dbl>           <dbl>
#>  1 Sepal.Length   4.3               4.3         3.000000             NaN
#>  2 Sepal.Length   4.4               4.4         3.033333               0
#>  3 Sepal.Length   4.5               4.5         2.300000             NaN
#>  4 Sepal.Length   4.6               4.6         3.325000               0
#>  5 Sepal.Length   4.7               4.7         3.200000               0
#>  6 Sepal.Length   4.8               4.8         3.180000               0
#>  7 Sepal.Length   4.9               4.9         2.950000               0
#>  8 Sepal.Length     5               5.0         3.120000               0
#>  9 Sepal.Length   5.1               5.1         3.477778               0
#> 10 Sepal.Length   5.2               5.2         3.425000               0
#> # ... with 116 more rows, and 1 more variables: Sepal.Width_sd <dbl>

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