-1

I have a list L and I want to compute for each elementconst/L_j and get a new list M with elements M_j = const/L_j. However, there are L_j elements that are zero. In this case it is preferred to assign such division to zero. I have made this the script below but it is slow.

temp = np.zeros((self.n_features, 1))
for t in range(self.n_features):
    if y[t]!=0:
        temp[t] = x/y[t] 

My question is similar to this but I want to apply it in a list. Is these a faster way to compute list M.

Thanks.

fuglede
  • 17,388
  • 2
  • 54
  • 99
Darkmoor
  • 862
  • 11
  • 29
  • There isn't a computationally faster way to compute this list. You are doing at most one access to compute each element, and you can't do less. – NiVeR Jun 10 '18 at 13:48
  • @NiVeR: The purpose of NumPy is to speed up exactly such computations through vectorization; doing so in this case is orders of magnitude faster than the naive loop solution. – fuglede Jun 10 '18 at 14:03

5 Answers5

3

Just another way with time complexity of O(N), iterate over the elements:

M = [0 if l == 0 else constant/l for l in L]
amin
  • 1,413
  • 14
  • 24
  • Complexity is mostly irrelevant here; a vectorized solution will also be linear time but with a constant that's orders of magnitude smaller. – fuglede Jun 10 '18 at 14:05
  • @fuglede you are totally right, the point is that it can be done by just 1 iteration over data (coefficient free). – amin Jun 10 '18 at 14:09
1

Assuming that your array is called L, you could do something like

M = x/L
M[np.isinf(M)] = 0

The additional time required to zero out the bad elements is negligible, even when the number of infinites is large:

In [20]: L = np.random.randint(0, 2, 100000)

In [21]: %timeit [0 if l == 0 else 10/l for l in L]
34.9 ms ± 2.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [23]: %timeit M = 10/L
263 µs ± 11.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [24]: %timeit M[np.isinf(M)] = 0
983 ns ± 40.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
fuglede
  • 17,388
  • 2
  • 54
  • 99
0
def transform_to_M(const, x):
    if x==0:
       return 0
    return const/x

np.fromiter((transform_to_M(const, i) for i in y), float, count=len(y))
artona
  • 1,086
  • 8
  • 13
0

You can do it using math.inf.

from math import inf

lst = [2, 1, 0, -1, -2]
const = 1

res = [const / (l or inf) for l in lst]

print(res) # [0.5, 1.0, 0.0, -1.0, -0.5]
Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73
0

The fastest, easiest and most pythonic way to do this is array masking:

M = x / L
M[L == 0] = 0

This is one function evaluation faster than fuglede's code.

JE_Muc
  • 5,403
  • 2
  • 26
  • 41