2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Wie erstelle ich Grafiken, was ist zu beachten?

Moderatoren: EDi, jogo

Antworten
SebastianL
Beiträge: 7
Registriert: Sa Dez 28, 2019 5:16 pm

2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Beitrag von SebastianL »

Hallo liebes Forum,

ich versuche meine Peakflow-Werte (Asthma) in einem plot darzustellen. Leider sind die Werte sehr volatil.

Es gibt einen Wert morgens und einen Wert abends. Diese sollen nicht zeitlich verschoben sein! Sondern immer zum gleichen Zeitpunkt dargestellt werden.

Dies sind meine Befehle, die ich eingebe:
peakflow <- read.table("Peakflow.txt", sep = ";", header = TRUE)
m.peakflow <- peakflow$morgens
a.peakflow <- peakflow$abends
m.peakflow <- m.peakflow[length(m.peakflow):1]
a.peakflow <- a.peakflow[length(a.peakflow):1]
plot(m.peakflow, type = "b", col="blue")
lines(a.peakflow, type = "b", col="red")

Mein Problem ist, dass die unteren Werte einfach durch die X-Achse abgeschnitten werden.

Die Peakflowwerte sollten in 10er Schritten etwas unterhalb des tiefsten Wertes beginnen (dynamisch).

Beim Datum hätte gerne alle 7 Tage ein Datum bzw. später wenn ich mehr Daten habe monatlich oder jährlich.

Kann mir da bitte jemand helfen?

Vielen Dank im Voraus und mit besten Grüßen und schöne Feiertage
Sebastian
Hufeisen
Beiträge: 162
Registriert: Fr Aug 31, 2018 6:34 pm

Re: 2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Beitrag von Hufeisen »

Hallo Sebastian,

das Abschneiden der Werte kann man lösen, indem zuerst die Grafik mit ihren Abmessungen initialisiert wird und dann die Daten eingetragen werden. Ich versuche dein Problem mit dem Datensatz mtcars nachzustellen.

Code: Alles auswählen

par(mfrow = c(1, 2))

# Problem: Datenpunkte werden abgeschnitten
plot(mtcars$mpg, mtcars$disp, type = "p", col = "blue")
lines(mtcars$hp, type = "b", col = "red")
grid()

# Lösung: Leeres Feld plotten und dann Daten eintragen
plot(mtcars$mpg, mtcars$disp, type = "n", ylim = c(min(c(mtcars$disp, mtcars$hp)), max(c(mtcars$disp, mtcars$hp))),
     ylab = "disp = blue, hp = red")
lines(mtcars$disp, type = "p", col = "blue")
lines(mtcars$hp, type = "b", col = "red")
grid()
Für die übrigen Punkte müsstest du uns deine Daten oder ein entsprechendes Beispiel zur Verfügung stellen. Ich kann mir nicht vorstellen, wie dein Plot aussehen soll. Du plottest die Objekte m.peakflow und a.peakflow. Aber wo kommt das Datum ins Spiel?
SebastianL
Beiträge: 7
Registriert: Sa Dez 28, 2019 5:16 pm

Re: 2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Beitrag von SebastianL »

Guten Abend,

vielen Dank für die schnelle Antwort!

Ich habe nun meine Daten angefügt. Es ist eine Datei mit 3 Spalten: Datum, Wert morgens und Wert abends.

Könnten Sie mir das noch mal an meinem Beispiel erklären?
Das wäre sehr hilfreich.

Vielen Dank im Voraus und mit freundlichen Grüßen
Sebastian
Dateianhänge
Peakflow - Kopie.txt
(382 Bytes) 46-mal heruntergeladen
Hufeisen
Beiträge: 162
Registriert: Fr Aug 31, 2018 6:34 pm

Re: 2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Beitrag von Hufeisen »

Hallo Sebastian,

ich habe es nicht hinbekommen, ein pädagogisch wertvolles Beispiel zum Nachbasteln zu bauen, deshalb solltest du versuchen, meinen Code nachzuvollziehen. Die Handhabung von Daten ist recht fummelig (zumindest für mich).

Zur Erklärung: Deine y-Achse schneidet Werte ab, weil Du die Grafik mit einem Datensatz erstellst (m.peakflow) und dann einen zweiten mit einzeichnen lässt, der aber niedrigere Werte als der erste enthält (a.peakflow). R erstellt die Abmessungen für das Grafikfeld aber mit dem Befehl plot. Daher muss man R dort die erforderlichen Grenzen für alle einzuzeichnenden Datensätze mitgeben. Das macht im Befehl plot() das Argument ylim. Hier setze ich die untere Grenze für die y-Achse auf den kleinsten Wert aus beiden Datensätzen und ziehe außerdem 10 ab, weil Du das zusätzlich so wolltest, wenn ich Dich richtig verstanden habe.
Die Anzahl der zu setzenden ticks auf der x-Achse habe ich mit nrow(peakflow) - c(0:2) * 7 noch manuell gesetzt. Da müsste man sich später was einfallen lassen, um bei einem veränderten Zeitraum die richtige Anzahl zu spezifizieren.

Code: Alles auswählen

# Deine Datei einlesen und angucken
peakflow <- read.table(file = 'http://forum.r-statistik.de/download/file.php?id=813&sid=1ed10ddecea3d7c72ed8b100cc79cf7f', sep = ";", header = TRUE)
str(peakflow) # Datum wird als Faktor erkannt

# Datum als solches deklarieren
peakflow$Datum <- as.Date(peakflow$Datum, format = "%d.%m.%Y") # Datum erkennen

# Spalten morgens und abends so wie das Datum absteigend sortiert
peakflow$m.peakflow <- peakflow$morgens[length(peakflow$morgens):1]
peakflow$a.peakflow <- peakflow$abends[length(peakflow$abends):1]

# plotten
par(mfrow = c(1, 2))

  # Dein Plot
  plot(peakflow$m.peakflow, type = "b", col="blue")
  lines(peakflow$a.peakflow, type = "b", col="red")
  grid()

  # Lösung: Leeres Feld ohne Achsen plotten, eigene Achse erstellen und dann Daten eintragen
  
    # Grafik initialisieren
    plot(peakflow$Datum, peakflow$m.peakflow,
         type = "n", axes = FALSE,
         ylim = c(min(c(peakflow$m.peakflow, peakflow$a.peakflow) - 10), max(c(peakflow$m.peakflow, peakflow$a.peakflow))),
         ylab = "morgens = blau, abends = rot")
    
    # x-Achse, Datensatz ist rückwärts sortiert
    axis(side = 1, 
         at = as.numeric(peakflow$Datum[nrow(peakflow) - c(0:2) * 7]),
         labels =  format(peakflow$Datum[nrow(peakflow) - c(0:2) * 7], "%d.%m.%Y"))
    
    # y-Achse
    axis(side = 2,
         at = seq(from = min(c(peakflow$m.peakflow, peakflow$a.peakflow)) - 10, to = max(c(peakflow$m.peakflow, peakflow$a.peakflow)), by = 10))
    
    # Daten eintragen
    lines(peakflow$Datum, peakflow$m.peakflow, type = "b", col = "blue")
    lines(peakflow$Datum, peakflow$a.peakflow, type = "b", col = "red")
    grid()
  
   
Dateianhänge
y-Achse abgeschnitten.png
SebastianL
Beiträge: 7
Registriert: Sa Dez 28, 2019 5:16 pm

Re: 2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Beitrag von SebastianL »

Guten Tag,

das sieht sehr gut aus vielen Dank dafür!

Ich werde es gleich ausprobieren.

Beste Grüße und einen guten Rutsch!
Sebastian
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Re: 2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Beitrag von bigben »

Hallo Sebastian,

ich hätte folgenden Vorschlag, der zwar nicht ganz Deinen Vorgaben entspricht, der aber die Zusammengehörigkeit von Morgen- und Abendwert deutlich visualisiert. Natürlich kann man da noch viel tun, um das hübscher aussehen zu lassen und mit der Funktion arrows könnte man etwas ähnliches auch noch kürzer coden, aber zunächst mal solltest Du prüfen, ob Dir dieser Ansatz gefällt:

Code: Alles auswählen

# hier erstmal Daten aufbereiten
pf <- read.table(header=TRUE, sep=";", 
                 text="Datum;morgens;abends
                 27.12.2019;520;520
                 26.12.2019;530;520
                 25.12.2019;530;530
                 24.12.2019;530;530
                 23.12.2019;540;520
                 22.12.2019;520;500
                 21.12.2019;530;500
                 20.12.2019;520;510
                 19.12.2019;540;510
                 18.12.2019;530;530
                 17.12.2019;540;530
                 16.12.2019;550;540
                 15.12.2019;550;540
                 14.12.2019;530;550
                 13.12.2019;520;530
                 12.12.2019;530;520
                 11.12.2019;520;530
                 10.12.2019;530;530"
                 )
pf$datum = as.Date(as.character(pf$Datum), format="%d.%m.%Y")
str(pf)

# ab hier Grafik erstellen

plot(NA, xlim=c(min(pf$datum), max(pf$datum)), ylim=c(480, 560),
     xaxt="n", xlab="Datum", ylab="peak exspiratory flow [l/min]")
for(i in 1:nrow(pf)){
  points(pf$datum[i], pf$morgens[i], pch=6)
  points(pf$datum[i], pf$abends[i], pch=17)
  lines(rep(pf$datum[i], 2), c(pf$morgens[i], pf$abends[i]), lty=3)
  cat(i)
}
axis(1, at=pf$datum, labels=pf$Datum)  # x-Achsenbeschriftung hier anpassen
legend("topright", legend=c("morgens", "abends"), pch=c(6, 17))
LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
SebastianL
Beiträge: 7
Registriert: Sa Dez 28, 2019 5:16 pm

Re: 2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Beitrag von SebastianL »

Hallo Bernhard,

das ist auf jeden Fall eine sehr interessante Darstellung.

Welche weiteren Verbesserungen würdest du vorschlagen? Ich bin relativ neu in R.

Was könntest du dir vorstellen? Und wie sähe der Code aus?

Vielen Dank im Voraus und beste Grüße
Sebastian
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Re: 2 Graphen in einem Plot (untere Werte einfach abgeschnitten+Skalierung ändern)

Beitrag von bigben »

Na die x-Achsenbeschriftung ist sicher noch optimierbar, da sollte man dem axes Kommando vielleicht nicht jeden sondern nur jeden x-ten Tag übergeben. Je nachdem, wie groß Du die Grafik machen willst.
Willst Du eine Grafik in Farbe oder schwarz-weiß? Nicht jede Zeitschrift mag bunte Einreichungen.
Man könnte waagerechte Hilfslinien einzeichnen, vielleicht Grenzen schlechten PEFs einzeichnen und so weiter. Minimum und Maximum der y-Achse sind fest codiert, das könnte man auch flexibel bzw. selbstanpassend machen. Mit mehr nachdenken fällt einem bestimmt noch was ein. Kurzum: Vieles geht, erstmal geht es darum, wie Du die Information am besten vermittelst, dann darum, wie viel Zeit und Mühe Du in die Ästhetik stecken willst.

LG,
Bernhard

Nachtrag: Du wolltest Code, ich könnte mir sowas gut vorstellen:

Code: Alles auswählen

plot(NA, xlim=c(min(pf$datum), max(pf$datum)), ylim=c(480, 560),
     xaxt="n", xlab="Datum", ylab="peak exspiratory flow [l/min]")
axis(4)
abline(h=seq(0,1000,10), col = "#A0A854", lty=3)
abline(v=seq(pf$datum[1], pf$datum[nrow(pf)], by=-1), col ="#A0A854", lty=3)
x.at <- seq(pf$datum[1], pf$datum[nrow(pf)], by=-7)
for(i in 1:nrow(pf)){
  lines(c(pf$datum[i]-.1, pf$datum[i]+.1), 
          c(pf$morgens[i], pf$abends[i]), lty=1, lwd=3, col="darkgrey")
  points(pf$datum[i]-.2, pf$morgens[i], pch=16, col="#FF1010")
  points(pf$datum[i]+.2, pf$abends[i], pch=17, col="#10A0FF")
}
axis(1, at=x.at, labels=x.at)  # x-Achsenbeschriftung hier anpassen
legend("topright", legend=c("morgens", "abends"), 
       pch=c(16, 17), col=c("#FF1010", col="#10A0FF"))
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
Antworten