Czym są dane cykliczne?
Dane cykliczne to rodzaj danych, które mają cykliczny lub powtarzający się charakter w określonym interwale lub cyklu. Te dane powtarzają się lub zmieniają w określony sposób w zależności od pewnego okresu czasu, kąta lub innego cyklu. Przykłady danych cyklicznych obejmują:
- Czas: Dane dotyczące godzin, minut, sekund, dni tygodnia, miesięcy mają cykliczny charakter, na przykład, dni tygodnia powtarzają się co tydzień, a miesiące cyklicznie zmieniają się co rok.
- Kąt: Dane związane z kątami, takie jak kierunek w stopniach lub radianach.
- Sezonowość: Dane sezonowe, takie jak sprzedaż w sklepie, ilość ruchu na stronie internetowej lub temperatura w ciągu roku, wykazują cykliczne wzorce w określonych okresach, na przykład sezonowość w ciągu dnia, tygodnia, miesiąca lub roku.
Kodowanie dni tygodnia
Weźmy pod lupę kodowanie dni tygodnia. Załóżmy, że mamy kolumnę ‘dzien_tygodnia’ i adekwatne do nazwy kolumny wartości. Moglibyśmy każdej nazwie dnia przypisać wartość, na przykład od 1 do 7. Pierwsze pytanie czy zaczniemy od niedzieli czy od poniedziałku? Powiedzmy, że pod 1 będzie poniedziałek, pod 2 wtorek i tak dalej. Spójrzmy na nasze dane. Pomiędzy wartościami kodującymi poniedziałek a niedziele jest duża różnica, a w rzeczywistości niedziela stoi zaraz przed poniedziałkiem. Nie zachowaliśmy cykliczności danych.
import pandas as pd dni_tygodnia = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'] df = pd.DataFrame({'dni_tygodnia': dni_tygodnia}) df['kod_dnia'] = range(1, 8) df
No to może One-Hot-Encoder?
I w tym przypadku można napotkać na kilka potencjalnych problemów. Po pierwsze, utworzymy niepotrzebnie zbyt dużo nowych kolumn. Dni tygodnia mają 7 unikalnych wartości (poniedziałek, wtorek, …, niedziela). Jeśli zastosujemy kodowanie “One-Hot Encoder”, stworzymy 7 nowych kolumn, po jednej dla każdego dnia tygodnia. Każda obserwacja będzie miała wartość 0 w 6 z 7 nowych kolumn, co zajmuje dużo miejsca w pamięci i może prowadzić do nadmiernego rozrostu wymiarów danych, zwłaszcza w przypadku dużych zbiorów danych (a co by było, gdybyśmy tak zakodowali miesiące…). Po drugie, kolumny utworzone przez kodowanie “One-Hot Encoder” są skorelowane. Jeśli wiemy, że dzień tygodnia to poniedziałek (kolumna “poniedziałek” ma wartość 1), to wartości w pozostałych kolumnach wynoszą 0. I ostatni problem, czyli gubienie informacji o cyklu.
dni_tygodnia = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'] df = pd.DataFrame({'dni_tygodnia': dni_tygodnia}) df = pd.get_dummies(df, columns=['dni_tygodnia'], prefix='', prefix_sep='') df
Kodowanie cykliczne
Przy kodowaniu dni tygodnia często stosuje się kodowanie cykliczne, takie jak kodowanie za pomocą funkcji sinus i cosinus. Dzięki temu można reprezentować dni tygodnia na okręgu, gdzie poniedziałek sąsiaduje z wtorkiem a jednocześnie sąsiaduje z niedzielą, co odzwierciedla naturalny związek między dniami tygodnia. To bardziej kompaktowe i informacyjne podejście, zwłaszcza w przypadku analizy danych sezonowych i szeregów czasowych.
import pandas as pd import numpy as np import matplotlib.pyplot as plt dni_tygodnia = ['poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota', 'niedziela'] df = pd.DataFrame({'dni_tygodnia': dni_tygodnia}) # Mapowanie dni tygodnia na wartości numeryczne od 0 do 6 df['kod_dnia'] = range(0, 7) # Obliczenie sinusa i cosinusa na podstawie kolumny 'kod_dnia' df['sin_dnia'] = np.sin(2 * np.pi * df['kod_dnia'] / 7) df['cos_dnia'] = np.cos(2 * np.pi * df['kod_dnia'] / 7) df
plt.figure(figsize=(5, 5)) plt.scatter(df['sin_dnia'], df['cos_dnia']) plt.xlabel('sin_dnia') plt.ylabel('cos_dnia') plt.title('Reprezentacja cykliczna dni tygodnia') # Dodawanie podpisów do punktów for i, row in df.iterrows(): plt.annotate(row['dni_tygodnia'], (row['sin_dnia'], row['cos_dnia']), textcoords="offset points", xytext=(0,10), ha='center') plt.xlim(-1.2, 1.2) plt.ylim(-1.2, 1.2) plt.grid(True) plt.show()