max(dataframe['high'].shift(-3), dataframe['high'].shift(-2))
dediğinizde max
fonksiyonuna iki pandas serisi gönderiyorsunuz. s1
ve s2
diyelim yazması daha kolay olsun:
max(s1, s2)
max
'ın aşağı yukarı yaptığı şey kendisine verilen argümanları <
ile karşılaştırarak “en büyüğünü” bulmaktır. Yani ilk s1 < s2
'yi değerlendiriyor. Bakıyoruz ne döndürdüğüne bunun:
>>> # öylesine 2 seri
>>> s1 = pd.Series([12, 3, -5])
>>> s2 = pd.Series([0, 9, 87])
>>> s1 < s2
0 False
1 True
2 True
dtype: bool
s1 < s2
başka bir seri döndürdü (elemanları bu iki serinin eleman-eleman karşılaştırmasının sonucu oluşan). max
şimdi ne yapıyor? Bunu “boolean” bağlamında değerlendirmek istiyor. Niye? “Bu bundan daha küçük mü” evet/hayır sorusuna True/False bir cevap bulsun ki karşılaştırmayı sürdürüp en büyüğü bulsun. Örneğin max(4, 12)
'ye bakıyor olsaydık, 4 < 12
'nün boolean bağlamında True
vermesinden ötürü max
yanıtın 12 olduğunu söyleyebilir.
Ama s1 < s2
direkt True
veya False
döndürmedi, bool
'un içine paslayıp True
veya False
'a indirgenmesini bekleyelim (mesela if
'in devamına yazılan ifadeler dolaylı yoldan bool
'a tabi tutulur):
>>> bool(s1 < s2)
ValueError: The truth value of a Series is ambiguous.
Use a.empty, a.bool(), a.item(), a.any() or a.all().
?! Sizin aldığınız hatayı alıyoruz… Bir serinin doğruluk değerini belirlemekten kaçınıyor, düz Python’daki gibi liste doluysa True
'ya, değilse False
'a dönme gibi bir durum olmuyor. Böyle yapmasının makul olabileceğine dair şu örnekleri verebiliriz:
# eleman var ama False; True mu döndürsün False mu?
bool(pd.Series([False]))
# elemanların biri True diğeri False; ne döndürsün? Kuantum beni aşar :p
bool(pd.Series([True, False]))
Peki bunun üstesinden nasıl geliriz? İki seri arası eleman-eleman karşılaştırma yapabilecek “vektörize” fonksiyonlar sayesinde. numpy kullanmaktan imtina etmiyorsanız bunlardan ilki np.maximum
'dur:
>>> import numpy np
>>> np.maximum(s1, s2)
0 12
1 9
2 87
dtype: int64
pandas sınrılarında kalmak istiyorsanız s1
ve s2
'yi bir dataframe’de toplayıp onun kendine has max
metodunu kullabilirsiniz:
# "concatenate" ediyoruz; `axis=1` yan yana yapıştırmayı sağlıyor
>>> ikisi_beraber = pd.concat([s1, s2], axis=1)
>>> ikisi_beraber
0 1
0 12 0
1 3 9
2 -5 87
# Buradaki `axis=1` ise satır yönünde maksimum almasını söylüyor
# Dolayısıyla satır sayısı uzunluğunda bir seri elde ediyoruz
>>> maksimumlari = ikisi_beraber.max(axis=1)
>>> maksimumlari
0 12
1 9
2 87
dtype: int64
İkisi de aynı sonucu veriyor, np.maximum
daha kısa gibi duruyor. (Bu arada numpy kullanmakta bir sıkıntı görmeyeceğinizi düşünüyorum, en kötü ihtimalle pd.np
'den yürüyebilirsiniz :ğ)
Bunları göz önüne alıp kodunuzun ilgili kısmını şöyle değiştirebiliriz:
# birden fazla erişiyoruz, okunabilirliği de artırabilir kodu kısaltmasına ek
high = dataframe.high
...
(high.shift(-1) < np.maximum(high.shift(-3), high.shift(-2)))
...
Son olarak, shift(-1)
(ve -2, -3) kullanarak gelecekteki verilere erişiyorsunuz ama yaptığınız işten anlamıyorum o yüzden görmezden gelebilirsiniz bu eklemeyi :d
Kuantum pandas’ı aşıyor olabilir ama her yerde öyle olmak zorunda değil :d