NaN to oznaczenie ,,Not a Number'' które może pojawić się (na wydrukach z programu komputerowego) gdy procesor wykona jakąś operację ,,niedozwoloną''.
Dzielenie przez zero wykonywane jest przez współczesne bez problemów, generując jako wynik wartość ,,nieskończoność'' (która podczas wyprowdzania oznaczona będzie Inf
albo -Inf
). Procesor poprawnie wykonuje proste operacje na nieskończonościach, na przykłąd Inf + 1
to będzie Inf
. Natomiast próba dodawania $-\infty + \infty$ wygeneruje wynik NaN
.
duze = 1e300
male = 1e-300
dzielenie = duze/male
dzielenie
inf
dzielenie +5
inf
dzielenie - dzielenie
nan
Dane generowane przez RRDB będą zawierały takie znaczniki wszędzie tam, gdzie z jakichś powodów, nie udało się dokonać pomiarów. Na przykład plik AVERAGE86400.dat zawiera takie wartości
import numpy as np
import numpy.ma as ma
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (12,9) # Tu definiujemy rozmiary wykresu.
# Standardowo wydaje się być zbyt mały.
Funkcja genfromtext()
pozwala takie dane importować (ale zachowując wartości nan
w wybranych punktach. Sprawdźmy co się dzieje w 19 wierszu pliku AVERAGE86400.dat
?
np.genfromtxt('AVERAGE86400.dat')[19,:]
array([1.4557536e+09, nan])
np.isnan(np.genfromtxt('AVERAGE86400.dat')[19,1])
True
np.isnan(np.genfromtxt('AVERAGE86400.dat')[19,0])
False
Funkcja np.isnan()
pozwala sprawdzić czy zmienna przyjmuje wartośc NaN.
Zatem, wydaje się, że można tu użyć metody maskowania tablic opisanej gdzie indziej używając funkcji masked_invalid
lub masked_where
.
dane = np.genfromtxt('AVERAGE1800.dat')
temperatura = ma.masked_invalid(dane)
plt.plot(dane[:,0],dane[:,1],'.');
plt.show()
Okazuje się, że dane ciągle są nieprawdopodobne (zawierają błędne wartości). Zatem trzeba je filtrować ze względu na te wartości i NaN-y. Przyjmijmy, że temperatury większe od $55^o$ i mniejsze od $-25^o$ są nieprawdopodobne.
Można to zapewne zrobić na wiele sposobów: albo stworzyć dwie maski i połączyć je operatorem OR, albo spróbować od razu stworzyć maskę na podstawie złożonego warunku. Skorzystamy z funkcji np.logical_or
, która pozwala wykonywać operacje logiczne na elemantach całych tablic.
temp = dane[:,1]
temp = ma.masked_where(np.logical_or(np.isnan(temp), np.logical_or(temp < -25, temp > 55)), temp)
czas = ma.masked_array(dane[:,0], mask=temp.mask)
temp[~temp.mask].data
array([-0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.9689304 , -0.97132976, -0.99075683, -0.83426618, -0.59789995, -0.30984787, 0.06529007, 0.55961978, 1.01605712, 1.49648211, 2.02862636, 2.38894571, 2.54215373, 2.94817462, 3.58848959, 4.11365971, 4.39019901, 3.46231264, 1.9996722 , 1.3706712 , 1.02434473, 0.77193505, 0.76138098, 0.57264191, 0.32903536, 0.01951746, -0.27134013, -0.39613435, -0.50011568, -0.67656486, -0.8681121 , -1.08714175, -1.18525492, -1.28565313, -1.24108625, -1.04606541, -1.08572976, -1.33585592, -1.60743693, -1.85790117, -2.08819171, -2.28403202, -2.53051551, -2.75360595, -2.85811913, -2.88870606, -2.99370083, -3.19580117, -3.15671801, -2.74186134, -2.28816073, -1.69171359, -1.02051107, -0.10649571, 0.55675271, 0.91734664, 1.60928682, 1.96775816, 2.12463078, 1.88444471, 1.74624109, 2.0028115 , 2.2746414 , 2.55890763, 2.50252571, 1.62599862, 0.26635421, -0.50358427, -0.98479002, -1.40007052, -1.67309828, -1.90303818, -2.17718339, -2.45854333, -2.69389698, -2.9804397 , -3.21216814, -3.37002201, -3.63892863, -3.9121131 , -3.44242109, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.32476335, -3.37142357, -3.51366715, -3.50871543, -3.37796034, -3.39046239, -3.10425686, -3.01528678, -2.8449735 , -2.52775352, -2.33099223, -2.16743083, -2.03021482, -2.02666353, -1.92039705, -2.04087834, -2.07338505, -2.05382725, -2.09138797, -1.95651813, -1.58986749, -1.50969829, -1.62039588, -1.50575258, -1.43236731, -1.44103041, -1.42939079, -1.4403857 , -1.39900864, -1.3637495 , -1.3426858 , -1.31601555, -1.34638328, -1.37973848, -1.34939139, -1.34372559, -1.3643624 , -1.37567732, -1.31649507, -1.19616073, -1.21003961, -1.16580865, -0.92419366, -0.63649917, -0.25912707, -0.02178627, 0.40563403, 0.67488825, 0.90885667, 1.0746237 , 1.44658929, 1.43713447, 1.16494032, 0.98375386, 0.95851094, 1.00751924, 1.01762468, 0.81774303, 0.83232619, 0.83442293, 0.87528381, 0.87258487, 0.90223848, 0.95190633, 1.19057823, 1.19491369, 1.29377344, 1.45033463, 1.66096858, 1.60056966, 1.47780845, 1.44014506, 1.48641699, 1.54128472, 1.59428292, 1.63644973, 1.59387903, 1.60590574, 1.6078418 , 1.61382814, 1.59810428, 1.55617152, 1.49411195, 1.46681 , 1.39870236, 1.36176584, 1.35547927, 1.36792649, 1.34065474, 1.45063501, 1.68485833, 1.98857957, 2.59823112, 3.2125596 , 3.59828842, 3.55584554, 3.89884217, 4.58764428, 4.46150343, 4.1222205 , 4.08124526, 4.07453335, 3.83789119, 3.57128158, 3.39105607, 2.6732194 , 1.9263623 , 1.3903127 , 1.06576122, 0.9290621 , 0.85108892, 0.71472104, 0.46200946, 0.28961528, 0.05223433, -0.13159077, -0.24962034, -0.40931991, -0.56371217, -0.64236233, -0.79759883, -1.21674488, -1.41533718, -1.43377337, -1.49950171, -1.61631932, -1.7912667 , -2.01220944, -2.17647829, -2.40088592, -2.41749333, -2.38312776, -2.47694158, -2.73418817, -3.03867776, -3.20700884, -3.37558817, -3.25663012, -2.75923466, -2.10442443, -1.50824765, -0.89508019, -0.12260412, 0.59729491, 1.14321798, 1.6565934 , 2.37697939, 2.51685072, 2.71776486, 3.16102275, 3.73784785, 4.43235326, 4.98068583, 4.52359916, 2.81570992, 1.59045274, 0.84730032, 0.40442651, 0.13273876, -0.11150835, -0.21906938, -0.46069369, -0.7553974 , -0.99919286, -1.22781625, -1.49587517, -1.80696982, -2.1868429 , -2.5097996 , -2.80082943, -3.05553462, -3.1488235 , -3.31342747, -3.44290583, -3.61827553, -3.77604984, -4.04064642, -4.26817368, -4.47379896, -4.77481949, -4.98215301, -5.04947649, -5.06595574, -5.08041844, -4.96337389, -4.63365679, -4.10623 , -3.61442886, -3.04414281, -2.38571858, -1.74436319, -0.96228349, -0.58046793, -0.04615267, 0.47187252, 0.82347588, 1.07181179, 1.36185046, -1.01576326, -1.80014157, -2.26408023, -2.7430987 , -3.09067551, -3.25374566, -3.50369328, -3.85212776, -4.02239798, -4.31083983, -4.55850166, -4.78828468, -4.95656198, -5.10658656])
czas = czas[~czas.mask].data
temp = temp[~temp.mask].data
plt.plot(czas, temp, '.')
plt.show()
Teraz powinniśmy jeszcze zastąpić czymś odrzucone wartości. Można, w tym celu, posłużyć sę interpolacją jak to opisano w innym notatniku. Nie trzeba — choć można — robić resamplingu, wystarczy użyć interpolacji aby zastąpić „puste miejsca” na wykresie danymi z interpolacji.
Unix timestamp może jest i wygodny, ale trudno zorientować się jakiego okresu czasu dotyczy powyższy wykres. Chcielibyśmy mieś os X opisaną jako daty.
W tym celu należy (niestety) skonwertować timestamp do postaci zrozumiałej dla oprogramowania. Służy do tego funkcja fromtimestamp
import matplotlib.dates as md
import datetime as dt
dates=[dt.datetime.fromtimestamp(ts) for ts in czas]
plt.xticks( rotation=25 )
ax = plt.gca()
xfmt = md.DateFormatter('%Y-%m-%d')
ax.xaxis.set_major_formatter(xfmt)
plt.plot(dates, temp, '.')
plt.show()
Czasami będziemy potrzebowali aby zastąpić czymś wartości w odrzuconych punktach. Można wówczas posłużyć się interpolacją w sposób opisany gdzie indziej.