У меня есть 2 кадра данных с номерами x и y одинаковой длины и входной номер a. Я хотел бы найти самый быстрый способ вычислить третий список z, например:
z[0] = a
z[i] = z[i-1]*(1+x[i]) + y[i]
без использования такого цикла:
a = 213
x = pd.DataFrame({'RandomNumber': np.random.rand(200)})
y = pd.DataFrame({'RandomNumber': np.random.rand(200)})
z = pd.Series(index=x.index, dtype=float)
z[0] = a
for i in range(1,len(x.index)):
z[i] = z[i-1]*(1+x.iloc[i]) + y.iloc[i]
Это выглядит как сложная операция, которую сложно векторизовать. numba
должно быть полезно.
Здесь действительно не получится избежать цикла из-за дополнений. Если вы попытаетесь разработать серию, вы увидите, что существуют факторы x(i-1)*x(i)*x(i+1)*…
Связанный: ответ cs95 на вопрос «Как я могу перебирать строки в Pandas DataFrame?» — Здесь перечислены другие варианты и есть ссылки на соответствующую документацию.
Эту функцию толком векторизовать не получится, разработка операции становится слишком сложной.
Например, z[i+1]
, выраженное через z[i-1]
, равно:
z[i-1]*(1+x[i])+y[i] + z[i]*(x[i+1]+x[i]*x[i+1]) + y[i]*x[i] + y[i+1]
И это ухудшается с каждым шагом
Как было предложено в комментарии, если скорость вас беспокоит, вы можете использовать numba
:
from numba import jit
@jit(nopython=True)
def f(a, x, y):
out = [a]
for i in range(1, len(x)):
out.append(out[i-1] * (1 + x[i]) + y[i])
return out
out = pd.Series(f(213, x['RandomNumber'].to_numpy(), y['RandomNumber'].to_numpy()), index=x.index)
Вывод (с использованием np.random.seed(0)
и 5 строк):
0 213.000000
1 365.772922
2 587.139217
3 908.025165
4 1293.097825
dtype: float64
Тайминги (200 строк):
# python loop
59.8 ms ± 908 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# numba
151 µs ± 968 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
Спасибо за решение. Нумба кажется очень интересным. Однако я не понимаю ваш код относительно numba. Насколько я понимаю, чтобы это работало, перед циклом должен быть декоратор @jit.
@Фред, конечно! С моей стороны это ошибка копирования/вставки ;)
разве
x,y
не должно быть сериалом?