Лучший способ избежать цикла

У меня есть 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]

разве x,y не должно быть сериалом?

Quang Hoang 03.05.2024 19:27

Это выглядит как сложная операция, которую сложно векторизовать. numba должно быть полезно.

Quang Hoang 03.05.2024 19:29

Здесь действительно не получится избежать цикла из-за дополнений. Если вы попытаетесь разработать серию, вы увидите, что существуют факторы x(i-1)*x(i)*x(i+1)*…

mozway 03.05.2024 19:30

Связанный: ответ cs95 на вопрос «Как я могу перебирать строки в Pandas DataFrame?» — Здесь перечислены другие варианты и есть ссылки на соответствующую документацию.

wjandrea 03.05.2024 19:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
4
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эту функцию толком векторизовать не получится, разработка операции становится слишком сложной.

Например, 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.

Fred Dujardin 07.05.2024 11:11

@Фред, конечно! С моей стороны это ошибка копирования/вставки ;)

mozway 07.05.2024 11:42

Другие вопросы по теме