Visualisierung vieler Variablen in einem Plot

25

Ich möchte zeigen, wie sich die Werte bestimmter Variablen (~ 15) im Laufe der Zeit ändern, aber ich möchte auch zeigen, wie sich die Variablen in jedem Jahr voneinander unterscheiden. Also habe ich diese Handlung erstellt:

Bildbeschreibung hier eingeben

Aber selbst wenn Sie das Farbschema ändern oder verschiedene Linien- / Formtypen hinzufügen, sieht dies unordentlich aus. Gibt es eine bessere Möglichkeit, diese Art von Daten zu visualisieren?

Testdaten mit R-Code:

structure(list(Var = structure(c(1L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 
6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 8L, 
8L, 8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 11L, 11L, 11L, 11L, 11L, 
11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 14L, 14L, 14L, 14L, 
14L, 14L, 14L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 
17L, 17L, 17L, 18L, 18L, 18L, 18L, 18L, 18L, 18L), .Label = c("A", 
"B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", 
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"), class = "factor"), 
    Year = c(2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 
    2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 1991L, 
    1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 1993L, 1996L, 2000L, 
    2004L, 2011L, 2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 
    2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 1991L, 
    1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 1991L, 1993L, 1996L, 
    2000L, 2004L, 2011L, 2015L, 1993L, 1996L, 2000L, 2004L, 2011L, 
    2015L, 2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 
    1991L, 1993L, 1996L, 2000L, 2011L, 2015L, 1991L, 1993L, 1996L, 
    2000L, 2004L, 2011L, 2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 
    2011L, 2015L), Val = c(25.6, 22.93, 20.82, 24.1, 24.5, 29, 
    25.55, 24.5, 24.52, 20.73, 25.8, 25.5, 29.5, 27.7, 25.1, 
    25, 24.55, 26.75, 25, 30.5, 27.25, 25.1, 22.4, 27.07, 26, 
    29, 27.2, 24.2, 23, 24.27, 27.68, 27, 30.5, 28.1, 24.9, 23.75, 
    22.75, 27.25, 25, 29, 28.45, 24, 20.25, 17.07, 24.45, 25, 
    28.5, 26.75, 24.9, 21.25, 20.65, 25.1, 24.5, 26.5, 25.35, 
    23.5, 21.93, 26.5, 24.5, 29, 29.1, 26.4, 28.1, 23.75, 26.5, 
    28.05, 27, 30.5, 25.65, 23.3, 23.25, 24.57, 26.07, 27.5, 
    28.85, 27.7, 22, 23.43, 26.88, 27, 30.5, 29.25, 28.1, 23, 
    23.8, 28.32, 27, 29.5, 29.15, 27.6)), row.names = c(1L, 4L, 
5L, 6L, 7L, 8L, 9L, 10L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 
21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 35L, 
36L, 37L, 38L, 39L, 40L, 41L, 44L, 45L, 46L, 47L, 48L, 49L, 50L, 
53L, 54L, 55L, 56L, 57L, 58L, 59L, 62L, 63L, 64L, 65L, 66L, 67L, 
68L, 69L, 70L, 71L, 72L, 73L, 74L, 75L, 78L, 79L, 80L, 81L, 82L, 
83L, 84L, 87L, 88L, 89L, 90L, 91L, 92L, 95L, 96L, 97L, 98L, 99L, 
100L, 101L, 104L, 105L, 106L, 107L, 108L, 109L, 110L), na.action = structure(c(2L, 
3L, 11L, 12L, 33L, 34L, 42L, 43L, 51L, 52L, 60L, 61L, 76L, 77L, 
85L, 86L, 93L, 94L, 102L, 103L), .Names = c("2", "3", "11", "12", 
"33", "34", "42", "43", "51", "52", "60", "61", "76", "77", "85", 
"86", "93", "94", "102", "103"), class = "omit"), class = "data.frame", .Names = c("Var", 
"Year", "Val"))
Amöbe sagt Reinstate Monica
quelle
2
Können Sie die Daten posten? Es ist leicht genug, grob ähnliche Beispiele zu finden, aber um den Faden zusammenzuhalten, helfen Menschen, die den gleichen Sandkasten zum Spielen haben. Welche Bedeutung hat die grüne Zone?
Nick Cox
Siehe auch Vorschläge in stats.stackexchange.com/questions/126480/…
Nick Cox
@NickCox Klar, hätte ich früher darüber nachdenken sollen! Ich habe die grüne Zone

Antworten:

42

Zufällig oder auf andere Weise hat Ihr Beispiel zunächst die optimale Größe (bis zu 7 Werte für jede der 15 Gruppen), um zu zeigen, dass grafisch ein Problem vorliegt. und zweitens, um andere und ziemlich einfache Lösungen zu ermöglichen. Die Grafik wird von Menschen aus verschiedenen Bereichen oft als Spaghetti bezeichnet , obwohl nicht immer klar ist, ob dieser Begriff als liebevoll oder als missbräuchlich gemeint ist. Die Grafik zeigt das kollektive oder familiäre Verhalten aller Gruppen, aber es ist ziemlich hoffnungslos, die zu untersuchenden Details anzuzeigen.

Eine Standardalternative besteht lediglich darin, die einzelnen Gruppen in separaten Feldern anzuzeigen. Dies kann jedoch genaue Vergleiche von Gruppe zu Gruppe erschweren. Jede Gruppe ist vom Kontext der anderen Gruppen getrennt.

Warum also nicht beide Ideen kombinieren: ein separates Panel für jede Gruppe, aber auch die anderen Gruppen als Hintergrund anzeigen? Dies hängt entscheidend von der Hervorhebung der Gruppe ab, die im Fokus steht, und vom Herunterspielen der anderen, was in diesem Beispiel aufgrund der Verwendung von Linienfarbe, -dicke usw. einfach genug ist.

Bildbeschreibung hier eingeben

In diesem Fall werden Details von möglicher praktischer oder wissenschaftlicher Bedeutung oder Interesse hervorgehoben:

  1. Wir haben nur einen Wert für A und M.

  2. In allen anderen Fällen haben wir nicht alle Werte für alle angegebenen Jahre.

  3. Einige Gruppen zeichnen hohe, einige niedrige und so weiter.

Ich werde hier keine Interpretation versuchen: Die Daten sind anonym, aber das ist auf jeden Fall das Anliegen des Forschers.

Je nachdem, was in Ihrer Software einfach oder möglich ist, können hier kleine Details geändert werden, z. B. ob Achsenbeschriftungen und -titel wiederholt werden (es gibt einfache Argumente für und gegen).

Das größere Problem ist, inwieweit diese Strategie allgemeiner funktioniert. Die Anzahl der Gruppen ist der Haupttreiber, mehr als die Anzahl der Punkte in jeder Gruppe. Grob gesagt könnte der Ansatz bis zu 25 Gruppen umfassen (etwa eine 5 x 5-Anzeige): Mit mehr Gruppen werden nicht nur die Grafiken kleiner und schwerer lesbar, sondern auch der Forscher verliert die Neigung, alle zu scannen Panels. Wenn es Hunderte (Tausende, ...) von Gruppen gäbe, wäre es normalerweise wichtig, eine kleine Anzahl von Gruppen auszuwählen, die gezeigt werden sollen. Einige Kriterien wie die Auswahl einiger "typischer" und einiger "extremer" Panels wären erforderlich. Dies sollte von den Projektzielen und einer Vorstellung davon abhängen, was für jeden Datensatz sinnvoll ist. Ein anderer Ansatz, der effizient sein kann, besteht darin, eine kleine Anzahl von Serien in jedem Feld hervorzuheben. So, Wenn es 25 breite Gruppen gäbe, könnte jede breite Gruppe mit allen anderen als Hintergrund gezeigt werden. Alternativ könnte es eine Mittelwertbildung oder eine andere Zusammenfassung geben. Die Verwendung von (z. B.) Haupt- oder unabhängigen Komponenten kann ebenfalls eine gute Idee sein.

Obwohl das Beispiel Liniendiagramme fordert, ist das Prinzip natürlich sehr allgemein. Beispiele könnten Multiplikationen, Streudiagramme, Modelldiagnosepläne usw. sein.

Einige Referenzen für diesen Ansatz [andere sind sehr willkommen]:

Cox, NJ 2010. Zeichnen von Teilmengen. Stata Journal 10: 670 & ndash; 681.

Knaflic, CN 2015. Storytelling mit Daten: Ein Leitfaden zur Datenvisualisierung für Geschäftsleute. Hoboken, NJ: Wiley.

Koenker, R. 2005. Quantile Regression. Cambridge: Cambridge University Press. Siehe Seiten 12-13.

Schwabish, JA 2014. Eine Anleitung für Ökonomen zur Visualisierung von Daten. Journal of Economic Perspectives 28: 209 & ndash; 234.

Unwin, A. 2015. Grafische Datenanalyse mit R. Boca Raton, FL: CRC Press.

Wallgren, A., B. Wallgren, R. Persson, U. Jorner und J.-A. Haaland. 1996. Statistiken und Daten grafisch darstellen: Bessere Diagramme erstellen. Newbury Park, Kalifornien: Salbei.

Hinweis: Das Diagramm wurde in Stata erstellt. subsetplotmuss erst mit installiert werden ssc inst subsetplot. Die Daten wurden von R kopiert und eingefügt, und die Wertelabels wurden so definiert, dass die Jahre als angezeigt werden 90 95 00 05 10 15. Der Hauptbefehl ist

subsetplot connected Val Year, by(Var) c(L) lcolor(gs12) backdrop(line) xtitle("") combine(imargin(small)) subset(lcolor(blue) mcolor(blue))

EDIT Extra Referenzen Mai, September, Dezember 2016; April, Juni 2017, Dezember 2018, April 2019:

Kairo, A. 2016. Die wahrheitsgemäße Kunst: Daten, Diagramme und Karten für die Kommunikation. San Francisco, CA: Neue Fahrer. S.211

Camões, J. 2016. Daten bei der Arbeit: Best Practices zum Erstellen effektiver Diagramme und Informationsgrafiken in Microsoft Excel . San Francisco, CA: Neue Fahrer. S.354

Carr, DB und Pickle, LW 2010. Visualisierung von Datenmustern mit Micromaps. Boca Raton, FL: CRC Press. S.85.

Grant, R. 2019. Datenvisualisierung: Diagramme, Karten und interaktive Grafiken. Boca Raton, FL: CRC Press. S.52.

Koponen, J. und Hildén, J. 2019. The Data Visualization Handbook. Espoo: Aalto KUNST Bücher. Siehe S.101.

Kriebel, A. und Murray, E. 2018. #MakeoverMonday: Verbessern der Visualisierung und Analyse von Daten, Diagramm für Diagramm. Hoboken, NJ: John Wiley. S. 303.

Rougier, NP, Droettboom, M. und Bourne, PE 2014. Zehn einfache Regeln für bessere Zahlen. PLOS Computational Biology 10 (9): e1003833. doi: 10.1371 / journal.pcbi.1003833 hier verlinken

Schwabish, J. 2017. Bessere Präsentationen: Ein Leitfaden für Wissenschaftler, Forscher und Wonks. New York: Columbia University Press. Siehe S.98.

Wickham, H. 2016. ggplot2: Elegante Grafiken für die Datenanalyse. Cham: Springer. Siehe S.157.

Nick Cox
quelle
+1, wunderbar, gibt es eine R- oder SAS-Funktion, die diese Art von Diagramm ausführen kann? Es ist wirklich toll.
Prognostiker
Ich mag diese Idee wirklich! Ich frage mich nur, wie ich das am besten in R mit ggplot2 plotten kann. Ich werde nur ein bisschen warten, bis ich die Antwort akzeptiere, hoffe, das ist in Ordnung.
2
Entschuldigung, ich habe keine Ahnung, wie man irgendetwas in SAS macht. Sicherlich kann alles, was Stata kann, auch R oder besser, oder so sagen mir seine Benutzer immer wieder ...
Nick Cox
@NickCox Kein Problem, ich habe es herausgefunden, es sieht wirklich gut aus und ist perfekt für meinen Zweck.
@NickCox, zwei weitere Referenzen sind: 1. Die Elemente der Datengrafik von WS Cleveland. Ein neues Buch. 2. Geschichtenerzählen mit Daten: Ein Leitfaden zur Datenvisualisierung für Geschäftsleute von Cole Nussbaumer Knaflic. Dieses Buch (Nr. 2) enthält eine Fallstudie Kapitel "Strategien zur Vermeidung des Spaghetti-Graphen".
Prognose
22

Als Ergänzung zu Nicks Antwort sehen Sie hier einen R-Code, mit dem Sie aus simulierten Daten ein ähnliches Diagramm erstellen können:

library(ggplot2)

get_df <- function(label="group A", n_obs=10, drift=runif(1)) {
    df <- data.frame(time=seq(1, n_obs), label=label)
    df$y <- df$time * drift + cumsum(rnorm(n_obs))
    return(df)
}
df_list <- lapply(sprintf("group %s", toupper(letters[1:9])),
                  function(label) { get_df(label) })
df <- do.call(rbind, df_list)
df$label2 <- df$label

p <- (ggplot(df, aes(x=time, y=y, group=label2)) +
      geom_line(size=0.9, alpha=0.8,
                data=df[, c("time", "y", "label2")], color="grey") +
      geom_line(size=1.1, color="black") +
      ylab("") +
      theme_bw() +
      theme(panel.border=element_blank()) +
      theme(strip.background=element_blank()) +
      facet_wrap(~ label))
p
ggsave("example_facet.png", p, width=10, height=8)

Beispiel Handlung

Adrian
quelle
6

Wenn Sie einen ggplot2Ansatz in R verwenden möchten, berücksichtigen Sie die facetshadeFunktion im Paket extracat. Dies bietet einen allgemeinen Ansatz, nicht nur für Liniendiagramme. Hier ist ein Beispiel mit Streudiagrammen (vom Fuß dieser Seite ):

data(olives, package="extracat")
library(scales)
fs1 <- facetshade(data = olives,
                  aes(x = palmitic, y = palmitoleic), f = .~Area)
fs1 + geom_point(colour = alpha("black", 0.05)) +
      geom_point(data = olives, colour = "red") +
      facet_wrap(f=~Area, nrow=3) + theme(legend.position="none")

Bildbeschreibung hier eingeben


BEARBEITEN: Verwenden von Adrians simuliertem Datensatz aus seiner früheren Antwort:

library(extracat)
facetshade(df, aes(x=time, y=y), f = .~label, bg.all = FALSE, keep.orig = TRUE) +
           geom_line(aes(x=time, y=y, group=orig.label),colour = alpha(1,0.3)) +
           geom_line(data=df, aes(colour=label), size = 1.2) + xlab("") + ylab("")

Ein anderer Ansatz besteht darin, zwei separate Ebenen zu zeichnen, eine für den Hintergrund und eine für die hervorgehobenen Fälle. Der Trick besteht darin, die Hintergrundebene mithilfe des Datensatzes ohne die Facettierungsvariable zu zeichnen. Für den Olivenöl-Datensatz lautet der Code:

data(olives, package="extracat")
ggplot(olives, aes(palmitic, palmitoleic)) + 
  facet_wrap(~Area, nrow=3) + 
  geom_point(data=olives %>% select(-Area), colour=alpha("black", 0.05)) + 
  geom_point(data=olives, colour="red") + 
  theme(legend.position="none")
Antony Unwin
quelle
1
Dies scheint ein netter allgemeiner Ansatz zu sein (+1), aber das spezielle Beispiel bezieht sich eher auf ein anderes Problem. Eine Reihe von wiederholten Streudiagrammen mit unterschiedlich hervorgehobenen Bereichen wird für die Frage nach Zeitreihen nicht funktionieren.
Sextus Empiricus
@martin Eigentlich ist es und das ist auch Adrians Lösung. Beachten Sie, dass er zwei identische Beschriftungsvariablen verwendet, sodass eine in der Hintergrundebene abgelegt werden kann. Die Codierungsidee wird anhand der nachstehenden Tidyverse-Notation deutlicher, und wie so oft kann eine elegante Formatierung von Grafiken die wichtigen Teile des Codes maskieren. ggplot(df %>% select(-label), aes(x=time, y=y, group=label2)) + geom_line(alpha=0.8, color="grey") + labs(y=NULL) + geom_line(data=df, color="red") + facet_wrap(~ label)
Antony Unwin
5

Hier ist eine Lösung, die von Kap. 11.3, Abschnitt "Texas Housing Data" in Hadley Wickhams Book on ggplot2 . Hier passe ich jeder Zeitreihe ein lineares Modell an, nehme die Residuen (die um den Mittelwert 0 zentriert sind) und zeichne eine Sammellinie in einer anderen Farbe.

library(ggplot2)
library(dplyr)
#works with dplyr version 0.4.3.9000 from Github (hadley/dplyr@4f2d7f8), or higher

df1 <- as.data.frame(list(Var = structure(c(1L, 2L, 2L, 2L, 2L, 2L, 2L, 
                                 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 
                                 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 8L, 
                                 8L, 8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 11L, 11L, 11L, 11L, 11L, 
                                 11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 14L, 14L, 14L, 14L, 
                                 14L, 14L, 14L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 
                                 17L, 17L, 17L, 18L, 18L, 18L, 18L, 18L, 18L, 18L), .Label = c("A", 
                                                                                               "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", 
                                                                                               "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"), class = "factor"), 
               Year = c(2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 
                        2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 1991L, 
                        1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 1993L, 1996L, 2000L, 
                        2004L, 2011L, 2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 
                        2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 1991L, 
                        1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 1991L, 1993L, 1996L, 
                        2000L, 2004L, 2011L, 2015L, 1993L, 1996L, 2000L, 2004L, 2011L, 
                        2015L, 2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 2011L, 2015L, 
                        1991L, 1993L, 1996L, 2000L, 2011L, 2015L, 1991L, 1993L, 1996L, 
                        2000L, 2004L, 2011L, 2015L, 1991L, 1993L, 1996L, 2000L, 2004L, 
                        2011L, 2015L), 
               Val = c(25.6, 22.93, 20.82, 24.1, 24.5, 29, 
                       25.55, 24.5, 24.52, 20.73, 25.8, 25.5, 29.5, 27.7, 25.1, 
                       25, 24.55, 26.75, 25, 30.5, 27.25, 25.1, 22.4, 27.07, 26, 
                       29, 27.2, 24.2, 23, 24.27, 27.68, 27, 30.5, 28.1, 24.9, 23.75, 
                       22.75, 27.25, 25, 29, 28.45, 24, 20.25, 17.07, 24.45, 25, 
                       28.5, 26.75, 24.9, 21.25, 20.65, 25.1, 24.5, 26.5, 25.35, 
                       23.5, 21.93, 26.5, 24.5, 29, 29.1, 26.4, 28.1, 23.75, 26.5, 
                       28.05, 27, 30.5, 25.65, 23.3, 23.25, 24.57, 26.07, 27.5, 
                       28.85, 27.7, 22, 23.43, 26.88, 27, 30.5, 29.25, 28.1, 23, 
                       23.8, 28.32, 27, 29.5, 29.15, 27.6)), 
               row.names = c(1L, 4L, 
                           5L, 6L, 7L, 8L, 9L, 10L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 
                           21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 35L, 
                           36L, 37L, 38L, 39L, 40L, 41L, 44L, 45L, 46L, 47L, 48L, 49L, 50L, 
                           53L, 54L, 55L, 56L, 57L, 58L, 59L, 62L, 63L, 64L, 65L, 66L, 67L, 
                           68L, 69L, 70L, 71L, 72L, 73L, 74L, 75L, 78L, 79L, 80L, 81L, 82L, 
                           83L, 84L, 87L, 88L, 89L, 90L, 91L, 92L, 95L, 96L, 97L, 98L, 99L, 
                           100L, 101L, 104L, 105L, 106L, 107L, 108L, 109L, 110L), 
               na.action = structure(c(2L, 
                          3L, 11L, 12L, 33L, 34L, 42L, 43L, 51L, 52L, 60L, 61L, 76L, 77L, 
                          85L, 86L, 93L, 94L, 102L, 103L), 
                .Names = c("2", "3", "11", "12","33", "34", "42", "43", "51", "52", "60", 
                           "61", "76", "77", "85", "86", "93", "94", "102", "103"), class = "omit"), 
                class = "data.frame", .Names = c("Var","Year", "Val"))


df1 %>%
        group_by(Var) %>%
        do(mutate(.,resid = resid(lm(Val ~ Year, data=., na.action = na.exclude)))) %>%
        ggplot(aes(Year, resid)) +
        labs(y=paste0("Val "), x="Year") +
        geom_line(aes(group = Var), alpha = 1/5) +
        geom_line(stat = "summary", fun.y = "mean", colour = "red")

Bildbeschreibung hier eingeben

knb
quelle
1
Die Hauptidee hier scheint zu sein, dass Sie eine Art zusammenfassende Kurve hinzufügen könnten, um das Auge und den Verstand zu unterstützen. Einverstanden, aber in Ihrer Antwort können Sie den Kompromiss beim Umschalten auf Mittelwert (oder Referenzniveau) 0 formulieren, anstatt die ursprünglichen Einheiten und Werte zu belassen. Fachexperten und / oder Kunden können durchaus in 24 oder 28 oder in beliebigen Werten denken. Natürlich sind die Daten hier nur ein Vehikel für die Diskussion, aber der Punkt ist sehr allgemein.
Nick Cox