Gestapeltes Zeitreihendiagramm
Ich habe mehrere Zeitreihen in verschiedenen Einheiten gemessen. Ich möchte ein gestapeltes Diagramm meiner Daten mit einer gemeinsamen x-Achse haben. Ein Beispiel wäre hier . Zur Veranschaulichung hier meine Daten.
nobs = 100;
TS1= RandomVariate[NormalDistribution[0, 1], nobs];
TS2= Accumulate[RandomVariate[NormalDistribution[0, 5], nobs]];
TS3= RandomInteger[{-10, 100}, nobs];
dates = DateRange[DatePlus[Today, Quantity[-nobs + 1, "Days"]], Today];
mytsdata = TimeSeries[#, {dates}] & /@ {TS1, TS2, TS3};
mergeddata = TimeSeriesThread[# &, mytsdata];
Ich kann verwenden DateListPlotoder StackedDateListPlotmeine Datensatz zu zeichnen mytsdataoder mergeddataaber keines dieser Plots dienen mein Interesse. Ich habe mit MATLAB ein Diagramm erstellt und es sieht so aus.
Ist es möglich, ein ähnliches Diagramm mit Ma-Codes zu erstellen? Die Flexibilität, die Diagrammeigenschaften zu ändern, würde viel Wert hinzufügen. Die Hauptanforderung ist, dass es nur eine x-Achse geben muss. Zeitreihen können unterschiedlich lang sein.
Update: Hier ist eine Liste mehrerer Zeitreihen mit unterschiedlichen Längen.
nobs = 100;
dates = DateRange[DatePlus[Today, Quantity[-nobs + 1, "Days"]], Today];
s1 = RandomVariate[NormalDistribution[0, 1], nobs];
s1ts = TimeSeries[s1, {dates}];
s2 = Accumulate[RandomVariate[NormalDistribution[0, 5], nobs - 25]];
s2ts = TimeSeries[s2, {dates[[26 ;;]]}];
s3 = RandomInteger[{-10, 100}, nobs - 50];
s3ts = TimeSeries[s3, {dates[[51 ;;]]}];
mergeddata2 =
TimeSeriesThread[# &, {s1ts, s2ts, s3ts},
ResamplingMethod -> Missing[]];
Ich möchte mergeddata2wie folgt zeichnen .
Update 2:
Mit Rohits Vorschlag konnte ich mein Diagramm mit den folgenden Codes erstellen:
drange = {mergeddata2["Dates"][[1]], mergeddata2["Dates"][[-1]]};
ResourceFunction["PlotGrid"][{
{DateListPlot[s1ts, Frame -> True,
PlotRange -> {drange, Automatic}]},
{DateListPlot[s2ts, Frame -> True,
PlotRange -> {drange, Automatic}]},
{DateListPlot[s3ts, Frame -> True, PlotRange -> {drange, Automatic}]}
}
]
Vorschläge für weitere Verbesserungen wären willkommen.
Antworten
Die Ressourcenfunktion PlotGrid bietet viele Optionen zur Steuerung des Layouts und der Achsen.
ResourceFunction["PlotGrid"][mytsdata // Map[DateListPlot /* List]]
So bekommen Sie das meiste, was Sie wollen.
Trotzdem habe ich diesen Beitrag ein paar Mal bearbeitet, um zur aktuellen Lösung zu gelangen.
Grid[{
{"TS1",DateListPlot[mytsdata[[1]], ImageSize -> 350, AspectRatio -> 1/2, ImagePadding -> {{25, 1}, {0, 0}}]},
{"TS2", DateListPlot[mytsdata[[2]], ImageSize -> 350, AspectRatio -> 1/2, ImagePadding -> {{25, 1}, {0, 0}}]},
{"TS3", DateListPlot[mytsdata[[3]], ImageSize -> 350, AspectRatio -> 1/2, ImagePadding -> {{25, 1}, {15, 0}}]},
{"", "TIME 2020"}
},
Alignment -> {Right, Left}]
Es folgen einige Erklärungen ...
Mathematica ermöglicht es Ihnen meines Wissens nicht, direkt zu tun, was Sie wollen.
Meine Lösung wird verwendet, Gridum die Entlassung von gewünschten Diagrammen zu replizieren.
Wie Sie sehen können, Gridhat 3 DateListPlots.
Ich verwende ImagePadding, um die linken vertikalen Achsen der Diagramme auszurichten. Ich habe keinen automatischen Weg gefunden, dies zu tun. Vielleicht hat jemand anderes einen Vorschlag.
Ich verwende auch ImagePadding, um jedes aufeinanderfolgende Diagramm mit dem darüber liegenden zu überlappen, um zu bewirken, dass die unteren Monatsbezeichnungen für die beiden oberen Diagramme ausgeblendet werden. Es gibt andere Möglichkeiten, dies zu tun. Mal sehen, was andere Antworten bringen.
Ich habe auch Ihre TIME & 2020 in der unteren Reihe der hinzugefügt Grid.
Um sicherzustellen, dass die TimeSeriesObjekte eindeutige Zeitsignaturen haben, habe ich einige Funktionen geschrieben, die zufällig verteilte Datumsbereiche erstellen . Diese Bereiche beginnen mit Todayeiner zufälligen Anzahl von Tagen plus oder minus und gehen für eine bestimmte Anzahl von Schritten in der Zeit zurück .
Außerdem biete ich eine Funktion an, die den gemeinsamen Bereich für eine Reihe verschiedener zufälliger Datumsbereiche zurückgibt (wie oben beschrieben).
Schließlich wird in dem Codeabschnitt, gibt es eine Funktion , die eine Anzahl von komponiert Wert Listen und ihre entsprechenden Datum Listen in TimeSeriesObjekte.
Clear[randf, randomDate, aroundToday, randomDates]
(* Returns an integer between 3 and 7 *)
randf = (RandomInteger[{3, 7}, #] &) /* First;
(* Returns a date that is a random number of days before the input date *)
randomDate[date_, random_ : randf, unit_ : "Days"] := DatePlus[date, {-random[1], unit}];
(* Returns a random number of days before of after Today's date *)
aroundToday[random_ : randf, unit_ : "Days"] := DatePlus[Today, {RandomChoice[{-1, 1}] random[1], unit}];
(* Returns n randomly generated days starting from around Today and going back in random number of steps *)
randomDates[n_, random_ : randf, unit_ : "Days"] := With[{r = randomDate[#, random, unit] &},
NestList[r, aroundToday[random, unit], n] // Reverse
]
(* Accepts lists of dates and returns their common range *)
dateRange[dates__] := Map[Through[{Min, Max}[#]] &, {dates}] // Transpose /* (
MapThread[Construct, {{Min, Max}, #}] &)
(* Composes TimeSeries objects from a list of date lists and a list of value lists *)
(* A working assumption is that corresponding dates and values sublists are of the same Length ns[i]] *)
(* The returned TimeSeries have a random number of the original entries removed *)
makeTimeSeries[dates_, values_, ns_, random_ : randf] := MapThread[
With[{t = #1, y = #2, is = RandomInteger[{1, #3}, randf[1]]},
TimeSeries[#2, {#1}] & @@ Transpose[ReplacePart[Transpose[{t, y}], is -> Nothing // Thread]]
] &, {dates, values, ns}]
Unter Verwendung des obigen Codes können wir wirklich ungleichmäßig verteilte Daten für die in angegebenen Werte generieren {s1, s2, s3}, bei denen es sich um Daten mit unterschiedlichen Längen in der OP-Bearbeitung handelt.
(* Obtained required data lengths *)
ns = Length /@ {s1, s2, s3};
(* Generate randomly spaced dates, starting from Today and extending back into the past *)
dates = Table[randomDates[n - 1], {n, ns}];
(* Finally, compose the corresponding TimeSeries objects *)
mytsdata = makeTimeSeries[dates, {s1, s2, s3}, ns]
(* Record the common range of the various date lists *)
rng = dateRange @@ ((#["Dates"] &) /@ mytsdata)
Auf meinem System ergab eine Auswertung des obigen Codes z.
Bitte beachten Sie, dass alle Zeitreihen unterschiedliche Bereiche und unterschiedliche Anzahlen von Beobachtungen haben.
Um nun eine Antwort auf das OP zu geben, habe ich die folgende Funktion verwendet:
ClearAll[manyPlots]
Options[manyPlots] = {"Plot1" -> None, "Plot2" -> None, "Plot3" -> None};
manyPlots[ts_, opts : OptionsPattern[manyPlots]] := Module[{opts1, opts2, opts3, allOpts},
allOpts = {opts1, opts2, opts3} = OptionValue[{"Plot1", "Plot2", "Plot3"}];
MapThread[DateListPlot[#1, Apply[Sequence, #2]] &, {ts, allOpts}] // List /* Transpose /* GraphicsGrid
]
Mit dieser manyPlotsFunktion kann der Benutzer verschiedene Optionen an die verschiedenen Diagramme übergeben. Z.B.
manyPlots[mytsdata,
"Plot1" -> {PlotLabel -> "a", PlotRange -> {rng, Automatic}},
"Plot2" -> {PlotLabel -> "b", PlotRange -> {rng, Automatic}, PlotStyle -> ColorData[97, "ColorList"][[2]]},
"Plot3" -> {PlotLabel -> "c", PlotRange -> {rng, Automatic}, PlotStyle -> ColorData[97, "ColorList"][[3]]}]
Verleiht den Plots unterschiedliche Beschriftungen und stellt sicher, dass sie alle über ihren gemeinsamen Bereich angezeigt werden. Außerdem wird das PlotStylefür das zweite und dritte Diagramm geändert.
Ich denke, dass es viele andere Änderungen gibt, die mit diesem Ansatz berücksichtigt werden können.