J'ai besoin de tracer un graphique à barres montrant les nombres et un graphique linéaire montrant le taux dans un seul graphique, je peux les faire séparément, mais quand je les mets ensemble, l'échelle de la première couche (c'est-à-dire la geom_bar
) est superposée par la seconde couche (c'est-à-dire la geom_line
).
Puis-je déplacer l'axe du geom_line
vers la droite?
ggplot2
implémentation native à l' intérieurscale_y_*
, actuellement appeléesec.axis
.Réponses:
Parfois, un client veut deux échelles y. Leur donner le discours "imparfait" est souvent inutile. Mais j'aime l'insistance de ggplot2 à faire les choses correctement. Je suis sûr que ggplot éduque en fait l'utilisateur moyen sur les techniques de visualisation appropriées.
Vous pouvez peut-être utiliser le facettage et l'échelle sans comparer les deux séries de données? - par exemple, regardez ici: https://github.com/hadley/ggplot2/wiki/Align-two-plots-on-a-page
la source
Ce n'est pas possible dans ggplot2 car je pense que les graphiques avec des échelles y séparées (pas des échelles y qui sont des transformations les unes des autres) sont fondamentalement défectueux. Quelques problèmes:
Ils ne sont pas inversibles: étant donné un point sur l'espace du tracé, vous ne pouvez pas le mapper de manière unique vers un point de l'espace de données.
Ils sont relativement difficiles à lire correctement par rapport à d'autres options. Voir A Study on Dual-Scale Data Charts by Petra Isenberg, Anastasia Bezerianos, Pierre Dragicevic, and Jean-Daniel Fekete for details.
Ils sont facilement manipulables pour induire en erreur: il n'y a pas de moyen unique de spécifier les échelles relatives des axes, les laissant ouverts à la manipulation. Deux exemples tirés du blog Junkcharts: un , deux
Ils sont arbitraires: pourquoi avoir seulement 2 échelles, pas 3, 4 ou dix?
Vous pourriez également vouloir lire la longue discussion de Stephen Few sur le sujet Les axes à double échelle dans les graphiques sont-ils jamais la meilleure solution? .
la source
À partir de ggplot2 2.2.0, vous pouvez ajouter un axe secondaire comme celui-ci (extrait de l' annonce ggplot2 2.2.0 ):
la source
En prenant les réponses ci-dessus et quelques ajustements (et pour tout ce que ça vaut), voici un moyen d'obtenir deux échelles via
sec_axis
:Supposons un ensemble de données simple (et purement fictif)
dt
: pendant cinq jours, il suit le nombre d'interruptions VS la productivité:(les plages des deux colonnes diffèrent d'environ 5).
Le code suivant dessine les deux séries qu'ils utilisent sur tout l'axe y:
Voici le résultat (au-dessus du code + quelques ajustements de couleurs):
Le point ( en dehors de l' utilisation
sec_axis
lors de la spécification du y_scale est de multiplier chaque valeur de la 2ème série de données avec 5 lors de la spécification de la série. Afin d'obtenir les libellés dans la définition de sec_axis, il faut alors diviser par 5 (et mise en forme). Donc , une partie cruciale dans le code ci-dessus est vraiment*5
dans la geom_line et~./5
dans sec_axis (une formule divisant la valeur actuelle.
par 5).En comparaison (je ne veux pas juger les approches ici), voici à quoi ressemblent deux graphiques superposés:
Vous pouvez juger par vous-même lequel transmet le mieux le message («Ne dérangez pas les gens au travail!»). Je suppose que c'est une façon juste de décider.
Le code complet pour les deux images (ce n'est pas vraiment plus que ce qui est ci-dessus, juste complet et prêt à fonctionner) est ici: https://gist.github.com/sebastianrothbucher/de847063f32fdff02c83b75f59c36a7d une explication plus détaillée ici: https: // sebastianrothbucher. github.io/datascience/r/visualization/ggplot/2018/03/24/two-scales-ggplot-r.html
la source
Il existe des cas d'utilisation communs sur deux axes, par exemple le climatographe montrant la température et les précipitations mensuelles. Voici une solution simple, généralisée à partir de la solution de Megatron en vous permettant de définir la limite inférieure des variables à autre chose que zéro:
Exemples de données:
Définissez les deux valeurs suivantes sur des valeurs proches des limites des données (vous pouvez jouer avec celles-ci pour ajuster les positions des graphiques; les axes seront toujours corrects):
Ce qui suit effectue les calculs nécessaires en fonction de ces limites et crée le tracé lui-même:
Si vous voulez vous assurer que la ligne rouge correspond à l'axe y droit, vous pouvez ajouter une
theme
phrase au code:qui colore l'axe de droite:
la source
ylim.prim
etylim.sec
.Vous pouvez créer un facteur d'échelle qui est appliqué au deuxième géom et à l'axe Y droit. Ceci est dérivé de la solution de Sebastian.
Remarque: en utilisant la
ggplot2
v3.0.0la source
L'ossature technique de la solution de ce défi a été fournie par Kohske il y a environ 3 ans [ KOHSKE ]. Le sujet et les détails techniques autour de sa solution ont été discutés sur plusieurs instances ici sur Stackoverflow [ID: 18989001, 29235405, 21026598]. Je ne fournirai donc qu'une variation spécifique et quelques explications, en utilisant les solutions ci-dessus.
Supposons que nous ayons certaines données y1 dans le groupe G1 auxquelles certaines données y2 dans le groupe G2 sont liées d'une manière ou d'une autre, par exemple la plage / échelle transformée ou avec du bruit ajouté. Donc, on veut tracer les données ensemble sur un seul tracé avec l'échelle de y1 à gauche et y2 à droite.
Si nous traçons maintenant nos données avec quelque chose comme
il ne s'aligne pas bien car la petite échelle y1 est évidement réduite par la plus grande échelle y2 .
L'astuce ici pour relever le défi est de tracer techniquement les deux ensembles de données par rapport à la première échelle y1 mais de rapporter le second par rapport à un axe secondaire avec des étiquettes montrant l'échelle d'origine y2 .
Nous construisons donc une première fonction d'aide CalcFudgeAxis qui calcule et collecte les caractéristiques du nouvel axe à afficher. La fonction peut être modifiée au gré des ayones (celle-ci mappe simplement y2 sur la plage de y1 ).
ce qui en donne:
Maintenant, j'ai encapsulé la solution de Kohske dans la deuxième fonction d'assistance PlotWithFudgeAxis (dans laquelle nous jetons l'objet ggplot et l'objet assistant du nouvel axe):
Maintenant, tout peut être rassemblé: le code ci - dessous montre comment la solution proposée pourrait être utilisée dans un environnement quotidien . L'appel de tracé ne trace plus désormais les données d'origine y2, mais une version clonée yf (contenue dans l'objet d'assistance précalculé FudgeAxis ), qui s'exécute à l'échelle de y1 . L'objet ggplot d'origine est ensuite manipulé avec la fonction d'assistance de Kohske PlotWithFudgeAxis pour ajouter un deuxième axe préservant les échelles de y2 . Il trace également le tracé manipulé.
Cela trace maintenant comme souhaité avec deux axes, y1 à gauche et y2 à droite
La solution ci-dessus est, pour faire simple, un hack tremblant limité. Comme il joue avec le noyau ggplot, il lancera des avertissements que nous échangeons des échelles post-factuelles, etc. Il doit être manipulé avec soin et peut produire un comportement indésirable dans un autre cadre. De plus, il peut être nécessaire de jouer avec les fonctions d'assistance pour obtenir la mise en page souhaitée. Le placement de la légende est un tel problème (il serait placé entre le panneau et le nouvel axe; c'est pourquoi je l'ai déposé). La mise à l'échelle / l'alignement des 2 axes est également un peu difficile: le code ci-dessus fonctionne bien lorsque les deux échelles contiennent le "0", sinon un axe est décalé. Donc définitivement avec quelques opportunités d'amélioration ...
Dans le cas où vous souhaitez enregistrer la photo, vous devez envelopper l'appel dans l'appareil ouvert / fermé:
la source
L'article suivant m'a aidé à combiner deux tracés générés par ggplot2 sur une seule ligne:
Plusieurs graphiques sur une page (ggplot2) par Cookbook for R
Et voici à quoi le code peut ressembler dans ce cas:
la source
multiplot
stackoverflow.com/a/51220506Pour moi, la partie délicate consistait à déterminer la fonction de transformation entre les deux axes. J'ai utilisé myCurveFit pour cela.
Trouver la fonction de transformation
fonction de transformation:
f(y1) = 0.025*x + 2.75
fonction de transformation:
f(y1) = 40*x - 110
Traçage
Notez comment les fonctions de transformation sont utilisées dans l'
ggplot
appel pour transformer les données "à la volée"Le premier
stat_summary
appel est celui qui définit la base du premier axe y. Le deuxièmestat_summary
appel est appelé pour transformer les données. N'oubliez pas que toutes les données prendront comme base le premier axe y. De sorte que les données doivent être normalisées pour le premier axe y. Pour ce faire, j'utilise la fonction de transformation sur les données:y=packetOkSinr*40 - 110
Maintenant , pour transformer le deuxième axe utiliser la fonction opposé au sein de l'
scale_y_continuous
appel:sec.axis=sec_axis(~.*0.025+2.75, name="y_second")
.la source
coef(lm(c(-70, -110) ~ c(1,0)))
etcoef(lm(c(1,0) ~ c(-70, -110)))
. Vous pouvez définir une fonction d'aide telle queequationise <- function(range = c(-70, -110), target = c(1,0)){ c = coef(lm(target ~ range)) as.formula(substitute(~ a*. + b, list(a=c[[2]], b=c[[1]]))) }
Nous pourrions certainement construire un terrain avec double Y axises à l' aide de la base R funtion
plot
.la source
Vous pouvez utiliser
facet_wrap(~ variable, ncol= )
sur une variable pour créer une nouvelle comparaison. Ce n'est pas sur le même axe, mais c'est similaire.la source
Je reconnais et suis d'accord avec hadley (et d'autres), que les échelles Y séparées sont "fondamentalement défectueuses". Cela dit - je souhaite souvent
ggplot2
avoir la fonctionnalité - en particulier, lorsque les données sont en grand format et que je veux rapidement visualiser ou vérifier les données (c'est-à-dire pour un usage personnel uniquement).Bien que la
tidyverse
bibliothèque facilite la conversion des données au format long (ce quifacet_grid()
fonctionnera), le processus n'est toujours pas trivial, comme indiqué ci-dessous:la source
sec_axis
.La réponse de Hadley fait une référence intéressante au rapport de Stephen Few sur les axes à double échelle dans les graphiques. Sont-ils jamais la meilleure solution? .
Je ne sais pas ce que les moyens OP avec « compte » et « taux » , mais une recherche rapide me donne chiffres et les taux , si je reçois des données sur les accidents dans Mountaineering Amérique du Nord 1 :
Et puis j'ai essayé de faire le graphique comme peu l'ont suggéré à la page 7 du rapport susmentionné (et suite à la demande d'OP de représenter graphiquement les décomptes sous forme de graphique à barres et les taux sous forme de graphique linéaire):
Et voici le résultat:
Mais je ne l'aime pas beaucoup et je ne peux pas facilement mettre une légende dessus ...
1 WILLIAMSON, Jed et al. Accidents in North American Mountaineering 2005. The Mountaineers Books, 2005.
la source
Il semble que ce soit une question simple, mais elle s'articule autour de 2 questions fondamentales. A) Comment gérer une donnée multi-scalaire tout en présentant dans un tableau comparatif, et deuxièmement, B) si cela peut être fait sans quelques pratiques de règle empirique de la programmation R telles que i) fusion des données, ii) facettage, iii) ajout une autre couche à une couche existante. La solution donnée ci-dessous remplit à la fois les conditions ci-dessus car elle traite des données sans avoir à les redimensionner et deuxièmement, les techniques mentionnées ne sont pas utilisées.
Voici le résultat,
Pour ceux qui souhaitent en savoir plus sur cette méthode, veuillez suivre le lien ci-dessous. Comment tracer un graphique de l'axe des 2 y avec des barres côte à côte sans redimensionner les données
la source
J'ai trouvé cette réponse m'a le plus aidé, mais j'ai trouvé qu'il y avait des cas marginaux qu'elle ne semblait pas gérer correctement, en particulier des cas négatifs, et aussi le cas où mes limites avaient une distance de 0 (ce qui peut arriver si nous saisissons nos limites de max / min de données). Les tests semblent indiquer que cela fonctionne de manière cohérente
J'utilise le code suivant. Ici, je suppose que nous avons [x1, x2] que nous voulons transformer en [y1, y2]. La façon dont j'ai géré cela était de transformer [x1, x2] en [0,1] (une transformation assez simple), puis [0,1] en [y1, y2].
Les éléments clés ici sont que nous transformons l'axe secondaire y avec
~((.-ylim.prim[1]) *b + ylim.sec[1])
puis appliquons l'inverse aux valeurs réellesy = ylim.prim[1]+(Temp-ylim.sec[1])/b)
. Nous devons également nous en assurerlimits = ylim.prim
.la source