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