Selecting items on a matrix based on indexes given by an array - python

Consider this matrix:
[0.9, 0.45, 0.4, 0.35],
[0.4, 0.8, 0.3, 0.25],
[0.5, 0.45, 0.9, 0.35],
[0.2, 0.18, 0.8, 0.1],
[0.6, 0.45, 0.4, 0.9]
and this list:
[0,1,2,3,3]
I want to create a list that looks like the following:
[0.9, 0.8, 0.9, 0.1, 0.9]
To clarify, for each row, I want the element of the matrix whose column index is contained in the first array. How can I accomplish this?

Zip the two lists together as below
a=[[0.9, 0.45, 0.4, 0.35],[0.4, 0.8, 0.3, 0.25],[0.5, 0.45, 0.9, 0.35],[0.2, 0.18, 0.8, 0.1],[0.6, 0.45, 0.4, 0.9]]
b=[0,1,2,3,3]
[i[j] for i,j in zip(a,b)]
Result
[0.9, 0.8, 0.9, 0.1, 0.9]
This basically pairs up each sublist in the matrix with the element of your second list in order with zip(a,b)
Then for each pair you choose the bth element of a

If this is a numpy array, you can pass in two numpy arrays to access the desired indices:
import numpy as np
data = np.array([[0.9, 0.45, 0.4, 0.35],
[0.4, 0.8, 0.3, 0.25],
[0.5, 0.45, 0.9, 0.35],
[0.2, 0.18, 0.8, 0.1],
[0.6, 0.45, 0.4, 0.9]])
indices = np.array([0,1,2,3,3])
data[np.arange(data.shape[0]), indices]
This outputs:
[0.9 0.8 0.9 0.1 0.9]

In the first array [0, 1, 2, 3, 3], the row is determined by the index of the each element, and the value at that index is the column. This is a good case for enumerate:
matrix = [[ ... ], [ ... ], ...] # your matrix
selections = [0, 1, 2, 3, 3]
result = [matrix[i][j] for i, j in enumerate(selections)]
This will be much more efficient than looping through the entire matrix.

Loop through both arrays together using the zip function.
def create_array_from_matrix(matrix, indices):
if len(matrix) != len(indices):
return None
res = []
for row, index in zip(matrix, indices):
res.append(row[index])
return res

Related

NumPy slicing squares in 2D array

I want to create a heightfield map that consists of squares of random height. Given an array of NxN, I want that every square of size MxM, where M<N, will be at the same random height, with the height sampled from a uniform distribution. For example, if we have N = 6 and M = 2, we would have:
0.2, 0.2, 0.6, 0.6, 0.1, 0.1,
0.2, 0.2, 0.6, 0.6, 0.1, 0.1,
0.5, 0.5, 0.3, 0.3, 0.8, 0.8,
0.5, 0.5, 0.3, 0.3, 0.8, 0.8,
0.6, 0.6, 0.4, 0.4, 0.9, 0.9,
0.6, 0.6, 0.4, 0.4, 0.9, 0.9
For now, I've come up with an inefficient way of doing it with 2 nested for loops. I'm sure there must be an efficient and elegant way to do that with NumPy slicing.
This solution using the repeat() method should work for N/M integer.
import numpy as np
N = 6
M = 2
values = np.random.random( [N//M, N//M] )
y = values.repeat( M, axis=0 ).repeat( M, axis=1 )
print(y)

Substituting the values from list of lists by the values of another list based on indices in python

Given lists are as follows:
mainList = [[0, 2, 1, 4, 3],
[0, 2, 1, 3, 4],
[1, 0, 2, 3, 4],
[2, 1, 0, 3, 4],
[1, 0, 2, 3, 4],
[0, 1, 2 ,3, 4],
[0, 2, 1, 3, 4]]
and list_indices = [0, 1, 2, 3, 4], list_value = [0.0, 0.2, 0.4, 0.4, 0.9].
The required list of lists is as follows:
mainList_mapped = [[0.0, 0.4, 0.2, 0.9, 0.4],
[0.0, 0.4, 0.2, 0.4, 0.9],
[0.2, 0.0, 0.4, 0.4, 0.9],
[0.4, 0.2, 0.0, 0.4, 0.9],
[0.2, 0.0, 0.4, 0.4, 0.9],
[0.0, 0.2, 0.4, 0.4, 0.9],
[0.0, 0.4, 0.2, 0.4, 0.9]]
Values of the mainList will be considered as indices and be replaced by the corresponding indices values in list_value. I tried but the code didn't work.
mainList_mapped = []
for ls in mainList:
for (i, j) in zip(ls, list_value):
ls[i] = j
mainList_mapped.append(ls)
A similar answer is here How to replace values at specific indexes of a python list? but I'm getting Error (TypeError: list indices must be integers or slices, not float) in getting my results. Any help will be appreciated.
You should be doing it like this:
mainList_mapped = []
for row in mainList:
row_mapped = []
for index in row:
row_mapped.append(list_value[index])
mainList_mapped.append(row_mapped)
You can create a function that rearranges a list based on given indices:
def rearrange(value, indices):
return [value[i] for i in indices]
Now apply this function to all the lists in the mainlist:
>>> result = [rearrange(list_value, indices) for indices in mainList]
>>> result
[[0.0, 0.4, 0.2, 0.9, 0.4],
[0.0, 0.4, 0.2, 0.4, 0.9],
[0.2, 0.0, 0.4, 0.4, 0.9],
[0.4, 0.2, 0.0, 0.4, 0.9],
[0.2, 0.0, 0.4, 0.4, 0.9],
[0.0, 0.2, 0.4, 0.4, 0.9],
[0.0, 0.4, 0.2, 0.4, 0.9]]
In this case it was easier because list_indices are sorted, but if it were shuffled, you could change the rearrange function like this:
mapping = dict(zip(list_indices, list_value))
def rearrange(mapping, indices):
return [mapping[i] for i in indices]
Try using a nested list comprehension:
print([[list_value[x] for x in i] for i in mainList])
Output:
[[0.0, 0.4, 0.2, 0.9, 0.4], [0.0, 0.4, 0.2, 0.4, 0.9], [0.2, 0.0, 0.4, 0.4, 0.9], [0.4, 0.2, 0.0, 0.4, 0.9], [0.2, 0.0, 0.4, 0.4, 0.9], [0.0, 0.2, 0.4, 0.4, 0.9], [0.0, 0.4, 0.2, 0.4, 0.9]]

Two denominational array slicing

I have a portion of Viterbi algorithm that I want to manipulate. I need to understand the slicing part in this code:
import numpy as np
A = np.array([[0.6, 0.2, 0.2], [0.5, 0.3, 0.2], [0.4, 0.1, 0.5]])
pi = np.array([0.5, 0.2, 0.3])
O = np.array([[0.7, 0.1, 0.2], [0.1, 0.6, 0.3], [0.3, 0.3, 0.4]])
states = UP, DOWN, UNCHANGED = 0, 1, 2
observations = [UP, UP, DOWN]
alpha = np.zeros((len(observations), len(states))) # time steps x states
alpha[:,:] = float('-inf')
backpointers = np.zeros((len(observations), len(states)), 'int')
***alpha[0, :] = pi * O[:,UP]***
in the last line print out the O[:,UP] what is should give me:
[0.7, 0.1, 0.2] I believe
instead, it gives me:
O[:,UP]
Out[15]: array([ 0.7, 0.1, 0.3])
I tried to look into this Understanding Python's slice notation
I couldn't understand why it changes the last element of the array.
Also, I run this:
O[:,UNCHANGED]
Out[17]: array([ 0.2, 0.3, 0.4])
I'm still newbie in python, I need some help
You are mixing up the notation for columns and rows.
You print O[:,UP] which gives you all the rows and just the "UP"th column (index 0).
Your O is:
array([[ 0.7, 0.1, 0.2],
[ 0.1, 0.6, 0.3],
[ 0.3, 0.3, 0.4]])
And O[:,0] is
#↓ this column
array([[ 0.7, 0.1, 0.2],
[ 0.1, 0.6, 0.3],
[ 0.3, 0.3, 0.4]])
where O[0,:] would be
array([[ 0.7, 0.1, 0.2], #This row
[ 0.1, 0.6, 0.3],
[ 0.3, 0.3, 0.4]])
And just to make the last part clear, O[:,UNCHANGED] is O[:,2] which is here:
#↓ this column
array([[ 0.7, 0.1, 0.2],
[ 0.1, 0.6, 0.3],
[ 0.3, 0.3, 0.4]])

Get Elements from one array based on list of index from another array

I have a 2 numpy array something like this
a = [array([ 0.1, 0.1, 0.1]), array([ 0.2, 0.2, 0.2])]
b = [0 0 0 1]
What I want is something like this --
c = [[0.1, 0.1, 0.1],[0.1, 0.1, 0.1],[0.1, 0.1, 0.1],[0.2, 0.2, 0.2]]
i.e. elements of a based on index of b.
Is there a way I can achieve this using numpy and vectorization i.e. without looping over the values?
If you store a as a two-dimensional numpy array:
>>> a = np.array([[0.1, 0.1, 0.1], [0.2, 0.2, 0.2]])
# result: array([[ 0.1, 0.1, 0.1],
# [ 0.2, 0.2, 0.2]])
or even convert a to a numpy array via a = np.array(a),
then you can use the list b to access the elements as desired:
>>> b = [0,0,0,1]
>>> print(a[b])
array([[ 0.1, 0.1, 0.1],
[ 0.1, 0.1, 0.1],
[ 0.1, 0.1, 0.1],
[ 0.2, 0.2, 0.2]])
and if you need a list as output then use tolist() method of the numpy arrays:
>>> (np.asarray(a)[b]).tolist()
[[0.1, 0.1, 0.1], [0.1, 0.1, 0.1], [0.1, 0.1, 0.1], [0.2, 0.2, 0.2]]
list comprehension
[a[x].tolist() for x in b]
import numpy
a = [numpy.array([ 0.1, 0.1, 0.1]), numpy.array([ 0.2, 0.2, 0.2])]
b = [0, 0, 0, 1]
Alternative 1:
print([a[x].tolist() for x in b])
Output:
[[0.1, 0.1, 0.1], [0.1, 0.1, 0.1], [0.1, 0.1, 0.1], [0.2, 0.2, 0.2]]
Alternative 2:
print(numpy.array(a)[b])
Output:
[[ 0.1 0.1 0.1]
[ 0.1 0.1 0.1]
[ 0.1 0.1 0.1]
[ 0.2 0.2 0.2]]
Alternative 3:
print(list(map(lambda i: a[i], b)))
Output:
[array([ 0.1, 0.1, 0.1]), array([ 0.1, 0.1, 0.1]), array([ 0.1, 0.1, 0.1]), array([ 0.2, 0.2, 0.2])]
Alternative 4:
from operator import itemgetter
print(list(itemgetter(*b)(a)))
Output:
[array([ 0.1, 0.1, 0.1]), array([ 0.1, 0.1, 0.1]), array([ 0.1, 0.1, 0.1]), array([ 0.2, 0.2, 0.2])]
Using numpy
If you want using numpy then:
print([a[i].tolist() for i in b])
Without using numpy :
import numpy as np
a = np.array([[0.1, 0.1, 0.1], [0.2, 0.2, 0.2]])
b = [0,0,0,1]
print([value_1.tolist() for value in b for index,value_1 in enumerate(a) if index==value])
above list comprehension is same as :
final=[]
for value in b:
for index,value_1 in enumerate(a):
if index==value:
final.append(value_1.tolist())
print(final)
output:
[[0.1, 0.1, 0.1], [0.1, 0.1, 0.1], [0.1, 0.1, 0.1], [0.2, 0.2, 0.2]]

Nested list to a dictionary of index counts

I'm very new to Python 3 and I'm working with Keras sigmoid activations which produce a nested list of probabilities.
I have a nested list that looks something like this:
[[0.1, 0.2, 0.3, 0.2, 0.4, 0.5]
[0.2, 0.3, 0.3, 0.3, 0.2, 0.1]
...
[0.1, 0.1, 0.4, 0.5, 0.1, 0.2]]
What I want to do is convert this list into a dictionary of indices wherein each index key has a corresponding frequency count of how many times in the list it meets a certain condition.
For example, given the three rows in the sample nested list above and given the condition:
element > 0.2
It will build the following dictionary:
[
0: 0
1: 1
2: 3
3: 2
4: 1
5: 1
]
This is because across the three nested lists, the value at index 0 is never greater than 0.2, the value at index 1 is greater than 0.2 only once (at the second nested list), the value at index 2 is greater than 0.2 for all the nested lists, the value at index 3 is greater than 0.2 for two nested lists (namely the second and third nested list), and so on.
Thank you very much!
With a as the list of lists of same lengths, we could convert to an array, giving us a 2D array. Then, compare against 2 and then sum the True matches along each column, as the counts. Finally setup the output dictionary from it.
Thus, one implementation would be -
C = (np.asarray(a)>0.2).sum(axis=0)
dict_out = {i:c for i,c in enumerate(C)}
np.count_nonzero could also be used in place np.sum for summing matches there.
Sample run -
In [209]: a
Out[209]:
[[0.1, 0.2, 0.3, 0.2, 0.4, 0.5],
[0.2, 0.3, 0.3, 0.3, 0.2, 0.1],
[0.1, 0.1, 0.4, 0.5, 0.1, 0.2]]
In [210]: C = (np.asarray(a)>0.2).sum(axis=0)
In [211]: C
Out[211]: array([0, 1, 3, 2, 1, 1])
In [212]: {i:c for i,c in enumerate(C)}
Out[212]: {0: 0, 1: 1, 2: 3, 3: 2, 4: 1, 5: 1}
Handling ragged sublists
For ragged sublists (lists having different lengths in input list), we could convert it to a regular array upon filling values with a invalid specifier (NaN seems suitable here) and then sum along the appropriate axis. Thus, to handle such a case, the modified implementation would be -
from itertools import izip_longest # For Python3, use zip_longest
C = (np.array(list(izip_longest(*a, fillvalue=np.nan)))>0.2).sum(1)
dict_out = {i:c for i,c in enumerate(C)}
Sample run -
In [253]: a
Out[253]:
[[0.1, 0.2, 0.3, 0.2, 0.4, 0.5, 0.7, 0.2],
[0.2, 0.3, 0.3, 0.3, 0.2, 0.1],
[0.1, 0.1, 0.4, 0.5, 0.1, 0.2, 0.1]]
In [254]: C = (np.array(list(izip_longest(*a, fillvalue=np.nan)))>0.2).sum(1)
In [255]: {i:c for i,c in enumerate(C)}
Out[255]: {0: 0, 1: 1, 2: 3, 3: 2, 4: 1, 5: 1, 6: 1, 7: 0}
I just write a simple code
a = [[0.1, 0.2, 0.3, 0.2, 0.4, 0.5], [0.2, 0.3, 0.3, 0.3, 0.2, 0.1],
[0.1, 0.1, 0.4, 0.5, 0.1, 0.2]]
dic = {'0': 0, '1': 0, '2': 0, '3': 0, '4': 0}
var = [x*0 for x in range(5)]
for array in a:
for i in range(5):
if array[i] > 0.2:
var[i] += 1
dic = {'0': var[0], '1': var[1], '2': var[2], '3': var[3], '4': var[4]}
print(dic)
While Divakar gives a really good answer with numpy, here's another way that doesn't use numpy which uses zip, list unpacking, enumerate, sum and dictionary comprehension. Just replace the i > 0.2 with what ever condition you want it to be:
x = [[0.1, 0.2, 0.3, 0.2, 0.4, 0.5], [0.2, 0.3, 0.3, 0.3, 0.2, 0.1], [0.1, 0.1, 0.4, 0.5, 0.1, 0.2]]
print({current_index:sum(i > 0.2 for i in values) for current_index, values in enumerate(zip(*x))})
>> {0: 0, 1: 1, 2: 3, 3: 2, 4: 1, 5: 1}

Categories

Resources