Cốt truyện chuỗi thời gian xếp chồng

Oct 21 2020

Tôi có nhiều chuỗi thời gian được đo bằng các đơn vị khác nhau. Tôi muốn có một đồ thị dữ liệu được xếp chồng lên nhau với một trục x chung. Một ví dụ sẽ là ở đây . Để minh họa, đây là dữ liệu của tôi.

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];

Tôi có thể sử dụng DateListPlothoặc StackedDateListPlotđể vẽ tập dữ liệu của mình mytsdatahoặc mergeddatanhưng không có đồ thị nào trong số này phục vụ lợi ích của tôi. Tôi đã tạo một biểu đồ bằng MATLAB và trông như thế này.

Có thể tạo một biểu đồ tương tự bằng cách sử dụng mã Ma không? Sự linh hoạt để thay đổi các thuộc tính đồ thị sẽ mang lại nhiều giá trị. Yêu cầu chính là phải có một và chỉ một trục x. Chuỗi thời gian có thể có độ dài khác nhau.

Cập nhật: Đây là danh sách một số chuỗi thời gian với độ dài khác nhau.

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[]];

Tôi muốn âm mưu mergeddata2như sau.

Thời gian và năm 2020 ở cuối biểu đồ là không bắt buộc. Cảm ơn bạn trước.

Cập nhật 2:

Kết hợp đề xuất của Rohit, tôi có thể tạo biểu đồ của mình với các mã sau:

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}]}
  }
 ]

Mọi đề xuất để cải thiện hơn nữa sẽ được hoan nghênh.

Trả lời

6 RohitNamjoshi Oct 21 2020 at 20:02

Chức năng tài nguyên PlotGrid có rất nhiều tùy chọn để kiểm soát bố cục và các trục.

ResourceFunction["PlotGrid"][mytsdata // Map[DateListPlot /* List]]

4 Jagra Oct 21 2020 at 19:39

Điều này giúp bạn có hầu hết những gì bạn muốn.

Điều đó nói rằng, tôi đã chỉnh sửa bài đăng này một vài lần để đi đến giải pháp hiện tại.

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}]

Một số giải thích sau ...

Mathematica, ít nhất là theo hiểu biết của tôi, không cho phép bạn làm những gì bạn muốn một cách dễ dàng.

Giải pháp của tôi sử dụng Gridđể tái tạo các biểu đồ mà bạn muốn.

Như bạn thấy, Gridcó 3 DateListPlots.

Tôi sử dụng ImagePaddingđể căn chỉnh các trục dọc bên trái của các mảnh đất. Tôi đã không tìm thấy một cách tự động để làm điều này. Có thể ai đó khác có một đề nghị.

Tôi cũng sử dụng ImagePaddingđể chồng chéo từng ô kế tiếp lên ô ở trên nó để ảnh hưởng đến việc nó ẩn các nhãn tháng dưới cùng cho 2 ô trên cùng. Có những cách khác để làm điều này. Hãy xem những câu trả lời khác mang lại những gì.

Tôi cũng đã thêm TIME & 2020 của bạn vào hàng dưới cùng của Grid.

3 joka Oct 21 2020 at 22:23

Chỉ để đảm bảo rằng các TimeSeriesđối tượng có các chữ ký thời gian duy nhất , tôi đã viết một vài hàm tạo các phạm vi ngày cách nhau ngẫu nhiên . Các phạm vi này bắt đầu từ Todaycộng hoặc trừ một số ngày ngẫu nhiên và quay ngược thời gian cho một số bước nhất định .

Ngoài ra, tôi cung cấp một hàm trả về phạm vi phổ biến cho một số phạm vi ngày ngẫu nhiên khác nhau (như được mô tả ở trên).

Cuối cùng, trong phần mã, có một chức năng soạn một số danh sách giá trị và danh sách ngày tháng tương ứng của chúng thành TimeSeriescác đối tượng.

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}]

Sử dụng đoạn mã trên, chúng ta có thể tạo các ngày có khoảng cách thực sự không đồng nhất cho các giá trị được đưa ra {s1, s2, s3}, là dữ liệu có độ dài khác nhau trong chỉnh sửa OP.

(* 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)

Trên hệ thống của tôi, một đánh giá của đoạn mã trên được tạo ra, ví dụ:

Vui lòng lưu ý cách tất cả các chuỗi thời gian có các phạm vi khác nhau và số lượng quan sát khác nhau.

Bây giờ, để cung cấp câu trả lời cho OP, tôi đã sử dụng hàm sau:

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
 ]

Các manyPlotschức năng, cho phép người sử dụng để vượt qua các lựa chọn khác nhau để các lô khác nhau. Ví dụ.

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]]}]

cung cấp các nhãn khác nhau cho các ô và đảm bảo rằng tất cả chúng đều được hiển thị trên phạm vi chung của chúng. Ngoài ra, nó sửa đổi PlotStylecốt truyện thứ hai và thứ ba.

Tôi nghĩ rằng có nhiều thay đổi khác có thể được đáp ứng bằng cách sử dụng cách tiếp cận này.