Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inverting floats in a list of lists [duplicate]

I have the output of a Markov transition table, which is a list of 59 lists each with 59 floats. I want to invert each of the non-0 floats, and then normalise the output so that again I have a list of probabilities which add up to 1.

I have read the textbook on list comprehensions, and that seems relevant, but I can't for the life of me understand how to implement it.

The list of lists is m

for i in range(59):
    [1/item for item in m[i] if item > 0.]
    i += 1

This runs, but it doesn't change m. Am I wrong to be using item in this code? Should I be using some other reference?

like image 623
Richard Hames Avatar asked Mar 15 '18 10:03

Richard Hames


2 Answers

[1/item for item in m[i] if item > 0.] creates a new list. Then you do nothing with that list. What Graipher is telling you is that you need a reference to the newly created list:
m[i] = <your list comprehension> will assign back to row i of your list of lists.

Also, consider numpy for element-wise operations. Demo:

>>> import numpy as np
>>> m = np.array([[1,2], [3, 0]])
>>> m = 1.0/m
>>> m
array([[ 1.        ,  0.5       ],
       [ 0.33333333,         inf]])
>>> m[m == np.inf] = 0
>>> m
array([[ 1.        ,  0.5       ],
       [ 0.33333333,  0.        ]])
like image 127
timgeb Avatar answered Oct 29 '22 00:10

timgeb


You need to assign it back to m[i] in the loop:

for i in range(len(m)):
    m[i] = [1./item if item != 0. else item for item in m[i]]

And the i+=1 is not needed because the for loop does that for you.

In order to avoid the sublist being shorter than the original sublist, you need to move the if from the end of the list comprehension (which basically filters which items are processed) to the front (so the value itself is a ternary expression that evaluates to 1/item or item, depending on the value of item).

At this point you should probably watch the presentation Loop like a Native and rewrite it for example as:

for i, x in enumerate(m):
    m[i] = [1./item if item != 0. else item for item in x]
like image 5
Graipher Avatar answered Oct 29 '22 00:10

Graipher