3
votes

Générer des histogrammes à partir du tuyau dplyr

J'ai un ensemble de données que je souhaite group_by () et générer un histogramme pour chaque groupe. Mon code actuel est le suivant:

df = data.frame(x1 = rep(c(1998,1999,2000),9),
            x2 = rep(c(1,1,1,2,2,2,3,3,3),3),
            x3 = rnorm(27,.5))

Cela génère cependant un histogramme unique de l'intégralité de x3 plutôt que plusieurs morceaux de x3 voici quelques exemples de données

df %>%
  group_by(x2) %>%
  with(hist(x3,breaks = 50))


5 commentaires

Les fonctions de base R telles que hist ne se soucient pas du group_by de dplyr.


? do devrait aider


hist ne prend qu'une colonne de données, il ignore votre regroupement. Utilisez plutôt ggplot ou faites


@infominer OP redirige vers avec , qui prend toute la trame de données. Le problème est que les fonctions extérieures à dplyr ignorent le regroupement --- ceci est tout aussi vrai pour ggplot que pour avec ou hist .


@Gregor, toi aussi. Je l'ai remarqué après avoir tapé mon commentaire. avec ggplot, ils devront faire des facettes ou avoir la possibilité d'utiliser le remplissage pour colorer les barres.


4 Réponses :


6
votes

Je pense qu'il est temps de passer à ggplot, par exemple:

library(tidyverse)

df %>% 
  ggplot(aes(x = x3)) + 
  geom_histogram(bins = 50) + 
  facet_wrap(~x2) # optional: use argument "ncols = 1"


3 commentaires

Il me manque peut-être quelque chose, l'OP a inclus des exemples de données


facet_grid (rows = vars (x2)) est plus cohérent avec la sortie attendue de l'OP. Et dans le code de création de données de l'OP, j'ai ajouté un zéro à chaque vecteur de colonne.


Cependant, je ne vois rien dans l'historique des modifications de l'article. Ne le dis pas comme une faute avec ton message



5
votes

Mon commentaire sur do est daté, je suppose. ? do nous indique la ?group_walk actuelle :

df %>% 
  group_by(x2) %>%
  do(h = hist(.$x3))

Dans les versions de dplyr group_walk , vous pouvez donc utiliser do:

df %>%
 group_by(x2) %>%
 group_walk(~ hist(.x$x3))

En supposant que vous ne vouliez que les effets secondaires de hist (histogramme imprimé), pas les valeurs renvoyées, vous pouvez ajouter un %>% invisible () à la fin de la chaîne pour ne pas imprimer le tibble résultant. p>


5 commentaires

D'où vient group_walk ? sos :: findFn ('group_walk') a trouvé 0 correspondance.


C'est une fonction de dplyr, vous devrez peut-être mettre à jour la version la plus récente du package.


@RuiBarradas Je suppose que c'était nouveau dans dplyr 0.8.0. Je vais ajouter une version do pour une compatibilité ascendante.


Merci! Cela fait exactement ce que je voulais. est-il possible de passer d'autres arguments dans l'appel group_walk () ? Par exemple, changer le titre principal pour être quelle que soit la variable de regroupement? Quelque chose comme `main = .x $ x2 '(cette syntaxe ne fonctionne pas avec" colonne inconnue ou non initialisée) -edit- l'a compris, besoin d'initialiser la colonne avec .y $ x2


Merci. En attendant, j'ai mis à jour le package dplyr .



2
votes

Vous pouvez utiliser la commande split.data.frame pour diviser les données en fonction des catégories, après avoir exécuté une commande hist dans la liste des blocs de données

list_df <- split.data.frame(df, f= df$x2)
par(mfrow = c(round(length(list_df), 0), 1))

for( lnam in names(list_df)){
  hist(list_df[[lnam]][, "x3"])

}

p>


1 commentaires

split est une fonction S3, donc si vous utilisez simplement split (df, f = df $ x2) , il enverra split.data.frame pour vous.



2
votes

J'aime beaucoup la réponse de @ Gregor avec group_walk , mais elle est toujours répertoriée comme expérimentale dans dplyr v0.8.0.1. Si vous voulez éviter de travailler avec des fonctions qui pourraient se casser plus tard, j'utiliserais la base split , puis purrr :: walk . J'utilise walk et plot pour éviter toutes les impressions de texte que donne hist .

library(dplyr)
library(purrr)

df %>%
  split(.$x2) %>%
  walk(~hist(.$x3) %>% plot())


1 commentaires

Bonne réponse! Considérez %>% invisible comme un moyen plus direct / général d'éviter la sortie de texte.