it-swarm.com.de

Kann ich mit ggplot2 eine Unterbrechung in der Achse einfügen?

Ich möchte ein Balkendiagramm erstellen, bei dem einer der Werte viel größer ist als alle anderen Werte. Gibt es eine Möglichkeit, eine unterbrochene y-Achse zu haben? Meine Daten sind wie folgt:

df <- data.frame(a = c(1,2,3,500), b = c('a1', 'a2','a3', 'a4'))

p <- ggplot(data = df, aes(x = b, y = a)) + geom_bar() 
p <- p + opts(axis.text.x=theme_text(angle= 90, hjust=1))  + coord_flip()
p

enter image description here

Gibt es eine Möglichkeit, meine Achse von 1 bis 10 und dann von 490 bis 500 laufen zu lassen? Ich kann mir keine andere Möglichkeit vorstellen, die Daten zu zeichnen (abgesehen von der Umwandlung, was ich nicht tun möchte)

44
djq

Wie an anderer Stelle bemerkt, ist dies nicht etwas, das ggplot2 gut handhaben wird, da gebrochene Äxte im Allgemeinen als fragwürdig angesehen werden.

Andere Strategien werden oft als bessere Lösungen für dieses Problem angesehen. Brian erwähnte einige (Facettierung, zwei Handlungen, die sich auf verschiedene Wertesätze konzentrieren). Eine andere Option, die die Leute zu oft übersehen, insbesondere bei Balkendiagrammen, ist die Erstellung eines Tabelle:

enter image description here

Betrachtet man die tatsächlichen Werte, verdeckt der 500 die Unterschiede zu den anderen Werten nicht! Aus irgendeinem Grund werden Tabellen als Daten einer Visualisierungstechnik nicht genügend berücksichtigt. Sie könnten einwenden, dass Ihre Daten viele, viele Kategorien haben, was in einer Tabelle unhandlich wird. Wenn ja, ist es wahrscheinlich, dass Ihr Balkendiagramm zu viele Balken hat, um auch sinnvoll zu sein.

Und ich streite nicht für Tische alle die Zeit. Aber sie sollten auf jeden Fall in Betracht gezogen werden, wenn Sie Balkendiagramme mit relativ wenigen Balken erstellen. Und wenn Sie Balkendiagramme mit Tonnen von Balken erstellen, müssen Sie dies möglicherweise trotzdem überdenken.

Schließlich gibt es noch die Funktion axis.break im Paket plotrix, die gebrochene Achsen implementiert. Soweit ich weiß, müssen Sie die Achsenbeschriftungen und -positionen jedoch selbst von Hand festlegen.

44
joran

Nein, ggplot nicht verwenden. Lesen Sie die Diskussion im Thread unter http://groups.google.com/group/ggplot2/browse_thread/thread/8d2acbfc59d2f247 , wo Hadley erklärt, warum dies nicht möglich ist die Daten, eine in einer bestimmten Region gezoomt).

26
Brian Diggs

Nicht mit ggplot, aber mit plotrix können Sie das leicht tun:

library(plotrix)
gap.barplot(df$a, gap=c(5,495),horiz=T)
20
Wouter

Nein, leider nicht

Die Befürchtung ist, dass das Zulassen von diskontinuierlichen Achsen zu einer Täuschung des Publikums führen wird. Es gibt jedoch Fälle, in denen nicht haben eine diskontinuierliche Achse zu Verzerrungen führt.

Wenn die Achse beispielsweise abgeschnitten ist, aber normalerweise in einem bestimmten Intervall (z. B. [0,1]) liegt, kann es sein, dass das Publikum das Abschneiden nicht bemerkt und verzerrte Schlussfolgerungen zu den Daten zieht. In diesem Fall wäre eine explizite diskontinuierliche Achse angemessener und transparenter.

Vergleichen Sie:

Example of good use of continuous vs discontinuous axis

15
milo

Acht Jahre später bietet das ggforce -Paket eine facet_zoom() -Erweiterung, die eine Implementierung von Hadley Wickhams Vorschlag ist, um zwei Diagramme (wie in Brian Diggs 'Antwort ).

Zoom-Facette

library(ggforce)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  facet_zoom(ylim = c(0, 10))

enter image description here

Leider gibt die aktuelle Version 0.2.2 von ggforce einen Fehler mit coord_flip() aus, sodass nur vertikale Balken angezeigt werden können.

Die gezoomte Facette zeigt die Variationen der kleinen Werte, enthält aber immer noch die große - jetzt beschnittene - a4 - Leiste. Der Parameter zoom.data Steuert, welche Werte in der gezoomten Facette angezeigt werden:

library(ggforce)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  facet_zoom(ylim = c(0, 10), zoom.data = ifelse(a <= 10, NA, FALSE))

enter image description here

Zwei Grundstücke

Hadley Wickham schlug vor

Ich denke, es ist viel angemessener, zwei Diagramme anzuzeigen - eines von allen Daten und eines von nur kleinen Werten.

Dieser Code erstellt zwei Diagramme

library(ggplot2)
g1 <- ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  coord_flip()
g2 <- ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  coord_flip() +
  ylim(NA, 10)

die zu einem Grundstück zusammengefasst werden können von

cowplot::plot_grid(g1, g2) # or ggpubr::ggarrange(g1, g2)

enter image description here

oder

gridExtra::grid.arrange(g1, g2) # or Egg::ggarrange(g1, g2)

enter image description here

Zwei Facetten

Dies wurde vorgeschlagen in einem Kommentar von Chase und auch von Brian Diggs in seiner Antwort , der Hadleys Vorschlag zur Verwendung interpretierte

facettierte Darstellungen, eine mit allen Daten, eine zoomte in einen bestimmten Bereich

bisher wurde jedoch kein Code für diesen Ansatz bereitgestellt.

Da es keine einfache Möglichkeit gibt, Facetten separat zu skalieren (siehe verwandte Frage , z. B.), müssen die Daten bearbeitet werden:

library(dplyr)
library(ggplot2)
ggplot() + 
  aes(x = b, y = a) +
  geom_col(data = df %>% mutate(subset = "all")) +
  geom_col(data = df %>% filter(a <= 10) %>% mutate(subset = "small")) +
  coord_flip() + 
  facet_wrap(~ subset, scales = "free_x")

enter image description here

3
Uwe

Ich bezweifle, dass in R irgendetwas von der Stange ist, aber Sie könnten die Daten als eine Reihe von 3D-Teilwürfeln anzeigen. 500 ist nur 5 * 10 * 10, also gut skalierbar. Der genaue Wert könnte ein Label sein. 

Dies sollte wahrscheinlich nur verwendet werden, wenn Sie müssen aus irgendeinem Grund eine grafische Darstellung haben.

1
Ed Staub

Eine Strategie besteht darin, die Achse zu ändern, um die Protokollskala zu zeichnen. Auf diese Weise können Sie den exponentiell höheren Wert um den Faktor 10 reduzieren

0
webscale