Python неявно, в отличие от C++, где вы почти должны объявить все. Python и numpy/pandas или другие модули имеют тонну оптимизированных функциональных возможностей - для того, чтобы вы могли работать без большого количества циклов или сравнения значений по значениям (что делают модули в фоновом режиме, часто это цикл for хотя - так что не думайте, что это обязательно быстрее, это просто красивое обложка).
Теперь давайте посмотрим на код
import numpy as np # no need for pandas here
def MMI(buffer, mmi_length):
# we will need to define two arrays here,
# shift(n) does not do what you want
window = np.asarray(buffer[1:mmi_length])
window_shifted = np.asarray(buffer[:mmi_length-1])
m = np.median(window)
# instead using all these explicit functions simply do:
nh = (window > m) & (window > window_shifted)
nl = (window < m) & (window < window_shifted)
nl = ~nh & nl # ~ inverts a lot of things,
# one of them are boolean arrays
# this does the right thing
return 100*(nh.sum()+nl.sum())/mmi_length
Теперь давайте объясним:
A Series в основном массив, в этом контексте, серия, кажется, как массовое убийство. Если вы сравниваете такой объект со скаляром, вы получите массив логических выражений, выражающий, какое значение удовлетворяло условию, а какое - нет (то же самое касается сравнения двух массивов, это приведет к булевому массиву, выражающему сравнение значений по значению).
На первом этапе вы сравниваете массив со скаляром (помните, что это будет логический массив) и еще один массив для другого массива (мы перейдем к части сдвига), а затем хотим логически и объединить результат сравнений. Хорошо, что вы хотите объединить два булевых массива, это будет работать неявно с помощью операции &
. Второй шаг аналогичен и будет работать неявно.
На третьем этапе вы хотите инвертировать булевский массив и объединить его с другим булевым массивом. Инверсия выполняется оператором ~
и может использоваться в других местах в других местах (например, для инвертирования подмножеств и т. Д.). Вы не можете использовать здесь оператор not
, поскольку его целью является преобразование его аргумента в значение истины (True/False) и возврат к противоположному - но каково значение истинности массива? Логическая и комбинация всех компонентов? Он не определен, поэтому вы получаете ошибку ambiguous
.
Логический массив sum()
логического массива всегда имеет значение True
значений в массиве, поэтому он даст правильные результаты.
Единственная проблема с вашим кодом заключается в том, что если вы примените shift(1)
к этой серии, то он добавит NaN
и обрезает последний элемент серии, так что вы получите объект равной длины.Теперь ваши сравнения не дают того, чего вы хотите больше, потому что что-то по сравнению с numpy.NaN
вернет False
. Чтобы преодолеть это, вы можете просто определить второй массив в начале (который затем делает устаревшие панды), используя тот же синтаксис, который вы уже использовали для window
.
PS: а NumPy массив это не список питона (все вышеперечисленное Numpy массивы!) NumPy массив представляет собой сложный объект, который позволяет для всех этих операций, со стандартными списками питона, вы должны работать ваш собственный для петель
Ian, учитывая, что ваш интерес проявляется как в ML & algo-trading, вы можете получить удовольствие от ** 'numpy' strided-tricks >>> http://www.scipy-lectures.org/ advanced/advanced_numpy/# indexing-scheme-strides ** для серий, которые в обеих моделях квантов и ML скоро вырастут до форм, которые не могут быть реализованы для обработки InRAM. Учитывая, что переупаковка огромных объемов данных в абстракцию панды не уступает выжившей реализации. Если вы сомневаетесь, сравните код на 1M, 10M, 100M строках данных, чтобы увидеть ослабление производительности (что, очевидно, может показаться прощающим при крошечных и небольших размерах матрицы ...). – user3666197
Спасибо. Я посмотрю, хотя, честно говоря, я настолько новичок в этом пространстве, что еще не достиг точки, когда у меня есть что-то полезное для применения к большому набору данных! –