Как избежать «RuntimeWarning: деление на ноль, обнаруженное в log10» в цикле for с более чем 20 000 элементов?

У меня есть список данных под названием data. Этот список содержит 21073 вложенных numpy массива. Каждый массив numpy, в свою очередь, содержит 512 значений. Парадигматически один вложенный массив numpy выглядит следующим образом:

[534.42623424, 942.2323, 123.73434 ...].

Более того, у меня есть еще один список данных под названием freq:

freq = [0.0009, 0.0053, 0.0034 ...], длина которого также составляет 512 цифр.

Цель: Я использую цикл for для вычисления линейной регрессии по методу наименьших квадратов через scipy.linregress(https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html) между каждым вложенным массивом numpy. в list и freq следующим образом:

for i in data:
slope = sp.stats.linregress(x=np.log10(freq), y=np.log10(i))[0]

Код работает. Но есть одна проблема.

Проблема: я предполагаю, что из-за огромного размера цикла for (= 21073) я всегда получаю ошибку RuntimeWarning: divide by zero encountered in log10. Важно отметить, что позиция в цикле for, где возникает эта ошибка, меняется каждый раз, когда я снова запускаю код. То есть иногда это происходит при n = 512, потом снова ближе к концу при n = 18766.

Вопрос: Прав ли я, что проблема связана с огромным размером цикла for. Как я могу решить проблему?

🤔 А знаете ли вы, что...
Python имеет множество фреймворков для веб-разработки, такие как Django и Flask.


98
2

Ответы:

Попробуй это:

for i in range(len(list)):
  slope = sp.stats.linregress(x=np.log10(freq[i]), y=np.log10(list[i]))[0]

а также рассмотрите возможность изменения имени переменной «список».


Решено

Ваша проблема не имеет ничего общего с размером вашего массива данных. Предупреждение выдается, потому что один или другой из ваших массивов содержит один или несколько нулей.

Вы можете отключить предупреждение, но необходимо учитывать, какое влияние это окажет на ваши результаты.

Например:

import numpy as np
assert np.log10(0) == -np.inf

Операции log10 векторизованы и поэтому не совпадают (как можно было бы ожидать) с индексом вашего цикла.

Не следует вычислять np.log10(freq) на каждой итерации цикла, поскольку это приводит к потере драгоценного времени. Он всегда будет возвращать один и тот же результат.

Учти это:

import numpy as np
from scipy.stats import linregress
from time import perf_counter

np.seterr(all = "ignore")

N = 21_073

data = [np.random.rand(512) for _ in range(N)]
freq = [np.random.rand(512)]

x = np.log10(freq)

if 0 in x:
    print("freq contains at least one zero value. Results may not be as expected")

start = perf_counter()

for datum in data:
    if 0 in datum:
        print("datum contains at least one zero value, Results may not be as expected")
    slope = linregress(x=x, y=np.log10(datum)).slope # type: ignore

print(f"Duration = {perf_counter()-start:.4f}s")

Выход:

Duration=0.6616s