Usuwanie trendu

Zadanie 1

  1. Zaimportować do MATLABa plik test_data.csv.

    Najprościej będzie użyć aplikacji Import Data; dane zawierają trzy kolumny: time, IR, RED zebrane z czujnika pulsu korzystającego z diod LED czerwonej i podczerwonej.

  2. Narysować wykres danych.

  3. Wybrać jeden z przebiegów (IR albo RED) i wykonać operację usuwania trendu detrend() (opis funkcji dalej). Wybrać metodę dającą (subiektywnie) najlepszy efekt.

  4. Narysować wykres przebiegu oryginalnego i po usunięciu trendu.

Zadanie 2

  1. Zaimportować do MATLABa plik temperatury.csv pochodzą one z pomiarów temperatury na początku listopada.

    Dane wyglądają jakoś tak

    Zawartość pliku temperatury.csv
    Zawartość pliku temperatury.csv

    Dane zawierają trzy kolumny:

    1. entity_id — spokojniemożna pominąć,
    2. state — zmierzona wartość temperatury,
    3. last_changed — czas pomiaru zapisany jako 2024-10-31T23:00:00.000Z
  2. Ponownie sugeruję skorzystanie z Import Data; pierwszej kolumny można nie importować, drugą należy zaimportować jako wartości numeryczne…

  3. Kłopot jest z kolumną trzecią — MATLAB chce ją traktować jako tekst. Trzeba mu podpowiedzieć, że jest to obiekt typu czas (w nomenklaturze MATLABowej datetime). I tu trzeba się trochę napracować.

    Format datetime opisany jest dalej.

  4. Import Tool prawidłowo rozpoznaje pierwsze dwie kolumny, ale trzecia traktowana jest jako tekst

    Import tool: widok pliku z danymi
    Import tool: widok pliku z danymi

    Import tool: format datetime
    Import tool: format datetime

    Klikając w more date formats przechodzimy do miejsca, w którym można wpisać odpowiedni format danych…

    Import tool: definicja własnego formatu daty
    Import tool: definicja własnego formatu daty

Reszta powinna być już łatwa…

Zadanie 3 — nieobowiązkowe

Linię trendu można (w przypadku Zadania 2) jako informację o średniej szybkości spadku temperatury (w stopniach na jednostkę czasu).

Z matematycznego punktu widzenia, zadanie sprowadza się do aproksymowania danych za pomocą linii prostej. Służy do tego funkcja fit() z pakietu Curve fitting toolbox (skrócony opis dalej). Niestety, nasze dane (last_changed) są typu datetime, a nie typu double i funkcja ta nie chce działać… Trzeba czas skonwertować do typu double. Służy do tego funkcja convertTo opisana dalej.

Również funkcja fit() opisana jest dalej…

Czasami (gdy „źle” dobierzemy format czasu) funkcja zwraca informację o postaci:

Warning: Equation is badly conditioned. Remove repeated data points or try centering and scaling.

Wyjaśnienie tego jest dosyć proste: gdy wartości $x$-ów są bardzo duże (w stosunku do $y$) odpowiedni parametr musi być bardzo mały.

W takich sytuacjach można dane „uprościć” odejmując od każdej wartości $x$ wartość minimalną (czas początkowy) czyli przesuwając wszystko na os w kierunku zera.

Albo przeskalować przedział czasu do przedziału $[0, 1]$.

detrend()

Opis funkcji na stronach WWW.

Wywołanie funkcji:

D = detrend(A)
D = detrend(A,n)
D = detrend(A,n,bp)
D = detrend(___,nanflag)
D = detrend(___,Name,Value)
  1. D = detrend(A) znajduje i usuwa trend opisany linią prostą;

    Gdy A jest wektorem — trend jest odejmowany od każdej wartości.

    Gdy A jest macierzą — wyliczany jest dla każdej kolumny

  2. D = detrend(A,n) znajduje i usuwa trend opisany wielomianem stopnia n. Gdy n równa się zero — usuwa wartość średnią.

  3. D = detrend(A,n,bp) jak w punkcje 2, ale tablica bp zawiera współrzędne punktów dzielących przedział przebiegu na odcinki; dla każdego odcinka wyznaczana jest inna funkcja trendu;

  4. Użycie dodatkowego parametru (nanflag) pozwala zdecydować co robić z pojawiającymi się (ewentualnie) wartościami NaN1. Parametr może przyjmować wartości:

    • "includemissing" (domyślnie) | "includenan" — pozostawia wartości NaN
    • "omitmissing" | "omitnan" — odrzuca z danych wartości NaN
  5. D = detrend(___,Name,Value) Ta forma pozwala na zdefiniowanie dodatkowych parametrów. Dodatkowe parametry to:

    • Continuous (przyjmuje wartości true (domyślnie) lub false) decyduje czy linia trendu ma być ciągła
    • SamplePoints — definiuje tablicę wartości zmiennej niezależnej2.
    • DataVariables — pozwala zdefiniować, na których kolummach tablicy A ma być wykonana operacja, n.p.: detrend(A,"DataVariables",["Var1" "Var2" "Var4"])
    • ReplaceValues (przyjmuje wartości true lub false) decyduje czy po usunięciu trendu nowe wartości mają zastąpić stare, czy mają być dodane do tablicy danych.

Użycie funkcji detrend() może być uciążliwe ( i wymagać wykonania wielu prób i błędów). Z tego powodu można w Live script skorzystać z zadania (task)

  • Przechodzimy do zakładki INSERT i tam wybieramy Task; otwiera się lista wielu zadań, z których można skorzystać. Zwracam uwagę, że jest tu również zadanie Import Data.

    Zadania (<em>tasks</em>) dostępne w Live Script
    Zadania (tasks) dostępne w Live Script

  • Wybieramy zadanie. Zostaje ono wstawione do skryptu.

    W pierwszym etapie decydujemy czy usuwa,y trend wielomianowy czy okresowy (w naszym przypadku ten pierwszy)

  • Na kolejnym panelu możemy wybrać parametry

    Zwracam uwagę na „ptaszek” w polu Autorun (prawy górny róg) — gdy jest on wstawiony wszystkie zmiany będą natychmiast przeliczane; gdy nie — trzeba kliknąć w w zielony trójkącik.

  • Gdy już będziemy zadowoleni z rezultatu — możemy poprosić o pokazanie kodu realizującego procedurę.

datetime()

MATLAB posiada specjalny typ danych służący do przechowywania czasu: datetime.

Żeby zadeklarować zmienną tego typu można użyć polecenia datetimne

t = datetime;

nada zmiennej t wartość aktualnej daty i czasu

>> t
t = 
  datetime
   13-Nov-2024 17:40:27

Tekstowy format czasu używany w różnych miejscach na świecie i przez różne aplikacje może się bardzo różnić. Jest norma (ISO 8601), która mówi jak czas powinno się zapisywać. I najogólniejszym zapisem jest format:

YYYY-MM-DDThh:mm:ss.SSS±hh:mm
  • pierwsza część (przed literą T) , to data,
  • część druga to aktualny czas (godzina, minuta, sekunda, po kropce tysięczne części sekund).
  • na końcu (±hh:mm) to określenie strefy czasowej (określanej jako przesunięcie czasowe w stosunku do czasu Greenwich); gdy te przesunięcie jest równe 00:00 może na końcu pojawić się litera Z (czytana jako Zulu).

Funkcja datetime pozwala również na konwersję różnych formatów czasu na format używany przez MATLABa, polecenie wygląda tak:

t = datetime(DateStrings,'InputFormat',infmt)
  • DateStrings to czas zapisany w postaci tekstowej

  • infmt zmienna mówiąca jak należy interpretować poszczególne znaki danych wejściowych:

    • yyyy rok (czetry cyfry)
    • mm miesiąc (dwie cyfry)
    • dd dzień (dwie cyfry)
    • HH godzina (dwie cyfry)
    • mm minuta (dwie cyfry)\
    • ss sekunda (dwie cyfry)
    • SSS tysięczne sekundy (trzy cyfry)

    pozostałe znaki, jeżeli występują muszą wystąpić tak jak wpisano.

Czas zapisany jako "2024-10-31T23:00:00.000Z" można opisać symboliczne tak:

"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

Polecenie

czas = datetime("2024-10-31T23:00:00.000Z", 'InputFormat', "yyyy-MM-dd'T'HH:mm:ss.SSS'Z")

skonwertuje dane na standardowy (dla MATLABa) format czasu…

convertTo()

Funkcja, jest — w zasadzie — dosyć prosta. Trzeba tylko wybrać odpowiedni format wyjściowy. Formatów wyjściowych typu double używanych do reprezentacji czasu jest kilka:

  • excelNumber of days since 0-Jan-1900, representing an Excel® date number.
  • excel1904Number of days since 0-Jan-1904, representing an Excel date number.
  • juliandateNumber of days since noon UTC 24-Nov-4714 BCE in the proleptic Gregorian calendar, representing the Julian Date.
  • modifiedjuliandateNumber of days since midnight UTC 17-Nov-1858, representing the Modified Julian Date.
  • posixtimeNumber of seconds since 1-Jan-1970 00:00:00 UTC, a point in time known as the Unix epoch.
  • yyymmddDates as YYYYMMDD numeric values. For example, 20140402 represents April 2, 2014. Obcina godziny!
  • datenumNumber of days since 0-Jan-0000 in the proleptic ISO calendar.

Przykład

>> czas = datetime("2024-10-31T23:00:00.000Z", 'InputFormat', "yyyy-MM-dd'T'HH:mm:ss.SSS'Z")
czas = 
  datetime
   31-Oct-2024 23:00:00
>> format longg
>> czasExcel = convertTo(czas,"Excel")
czasExcel =
          45596.9583333333
>> czasExcel1904 = convertTo(czas,"Excel1904")
czasExcel1904 =
          44134.9583333333
>> czasposix = convertTo(czas,"posix")
czasposix =
                1730415600
>> czasjuliandate = convertTo(czas,"juliandate")
czasjuliandate =
          2460615.45833333
>> czasyyyymmdd = convertTo(czas,"yyyymmdd")
czasyyyymmdd =
    20241031
>> czasdatenum = convertTo(czas,"datenum")
czasdatenum =
          739556.958333333
>> czasmodifiedjuliandate = convertTo(czas,"modifiedjuliandate")
czasmodifiedjuliandate =
          60614.9583333333

Jak się wydaje każdy (za wyjątkiem yyyymmdd) format będzie ok.

Ja, osobiście, jestem jakoś przywiązany do posixtime, ale Państwo mogą wybrać cokolwiek (choć początkowa data zerowy dzień stycznia jakoś mnie przeraża).

fit()

Funkcji używamy na jeden z poniższych sposobów

fitobject = fit(x,y,fitType)
fitobject = fit([x,y],z,fitType)
fitobject = fit(x,y,fitType,fitOptions)
fitobject = fit(x,y,fitType,Name=Value)
[fitobject,gof] = fit(x,y,fitType)
[fitobject,gof,output] = fit(x,y,fitType)

W tych zapisach

  • x — współrzędne $x$-owe

  • y — współrzędne $y$-owe

  • fittype — jeden z bardzo wielu modeli, które mogą być użyte; najpopularniejsze to:

    • poly1 — liniowy
    • poly2 — kwadratowy
    • … i tak dalej aż do poly9

    można również zdefiniować swój własny model korzystając, na przykład, z funkcji anonimowej

    Trzeba pamiętać, że ten parametr podajemy jako tekst to znaczy w cudzysłowach!

Funkcja zwraca wartości parametrów oraz przedziały ufności dla nich

Z fitobject można korzystać tak jak z funkcji.


  1. NaN to określenie Not a Number, które pojawia się gdy nie można określić wartości operacji arytmetycznej (na przykład Inf - INf czyli $\infty-\infty$ ); w przypadku danych pomiarowych tak oznacza się brakujące dane. ↩︎

  2. Współrzędne $x$-owe danych są bardzo istotne, gdy dane są próbkowane niejednostajnie. Czemu? Oczekuję odpowiedzi na te pytanie w sprawozdaniu↩︎

Poprzedni