How to average sub arrays in Numpy using broadcasting? - python-2.7

If there is a numpy array that is a list of 2d arrays, is there more efficient way than calling the mean function twice?
z = np.array([[[0, 0, 0],
[10, 10, 10]],
[[0, 0, 0],
[5, 5, 5]],
[[0, 0, 0],
[2, 2, 2]]])
print(z.mean(axis=2).mean(axis=1))
>[ 5. 2.5 1. ]

Related

How to choose specific row and column indices in C++ Eigen Array?

I wonder how it is possible to choose specific elements in Eigen Array given lists of indices for rows and columns. For example:
array = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
rowIndices = [0, 1, 2]
colIndices = [0, 1, 2]
expectedResult = [1, 5, 9]
I tried something similar to this but didn't get the expected result.
std::vector<int> indices = {0, 1, 2};
array(indices, indices);

Writting in sub-ndarray of a ndarray in the most pythonian way. Python 2

I have a ndarray like this one:
number_of_rows = 3
number_of_columns = 3
a = np.arange(number_of_rows*number_of_columns).reshape(number_of_rows,number_of_columns)
a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
But I want something like this:
array([[0, 100, 101],
[3, 102, 103],
[6, 7, 8]])
To do that I want to avoid to do it one by one, I rather prefer to do it in arrays or matrices, because later I want to extend the code.
Nothe I have change a submatrix of the initial matrix (in mathematical terms, in terms of this example ndarray). In the example the columns considered are [1,2] and the rows [0,1].
columns_to_keep = [1,2]
rows_to_keep = [0,1]
My first try was to do:
a[rows_to_keep,:][:,columns_to_keep] = np.asarray([[100,101],[102,103]])
However this doesn't modify the initial a, I am not having any error, so a=
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
So I have implemented a piece of code that goes do the job:
b = [[100, 101],[102, 103]]
for i in range(len(rows_to_keep)):
a[i,columns_to_keep] = b[i]
Al thought the previous lines do the job I am wondering how to do it slicing and in a faster fashion. Also in a way that with:
columns_to_keep = [0,2]
rows_to_keep = [0,2]
the desired output is
array([[100, 1, 101],
[3, 4, 5],
[102, 7, 103]]).
Many thanks!
Indexing with lists like [1,2] is called advanced indexing. By itself it produces a copy, not a view. You have to use one indexing expression, not two to assign or change values. That is a[[1,2],:] is a copy, a[[1,2],:][:,[1,2]] += 100 modifies that copy, not the original a.
In [68]: arr = np.arange(12).reshape(3,4)
Indexing with slices; this is basic indexing:
In [69]: arr[1:,2:]
Out[69]:
array([[ 6, 7],
[10, 11]])
In [70]: arr[1:,2:] += 100
In [71]: arr
Out[71]:
array([[ 0, 1, 2, 3],
[ 4, 5, 106, 107],
[ 8, 9, 110, 111]])
Doing the same indexing with lists requires arrays that 'broadcast' against each other. ix_ is a handy way of generating these:
In [73]: arr[np.ix_([1,2],[2,3])]
Out[73]:
array([[106, 107],
[110, 111]])
In [74]: arr[np.ix_([1,2],[2,3])] -= 100
In [75]: arr
Out[75]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
Here's what ix_ produces - a tuple of arrays, one is (2,1) in shape, the other (1,2). Together they index a (2,2) block:
In [76]: np.ix_([1,2],[2,3])
Out[76]:
(array([[1],
[2]]), array([[2, 3]]))
For the continuous rows and columns case, you can use basic slicing like this:
In [634]: a
Out[634]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [635]: b = np.asarray([[100, 101],[102, 103]])
In [636]: a[:rows_to_keep[1]+1, columns_to_keep[0]:] = b
In [637]: a
Out[637]:
array([[ 0, 100, 101],
[ 3, 102, 103],
[ 6, 7, 8]])

Gurobi and Python: how to query a dictionary using optimal variable solutions

I'm using Python and Gurobi and I'm having difficulty on how to optimal variable solutions to query a dictionary.
my_dict = {(i, j) : func(Z) for i in I for j in J}
my_dict results to be like this:
{(15687, 'B'): [[7, 0, 0, 0], [0, 7, 0, 0], [0, 0, 7, 0], [0, 0, 0, 7]],
...
(18906, 'C'): [[4, 0, 0, 3], [3, 0, 0, 3], [4, 0, 0, 0], [3, 0, 0, 0]}
Moreover I have a binary variable x[i, j, z] and an assignment constraint:
assignment = m.addConstrs((quicksum(x[i, j, z]
for z in range(len(my_dict[i, j]))) == 1
for i in I for j in J), "assignment")
Supposing I obtain as optimal solution variables
x[15687,'B',0] 1.000000
x[18906,'C',2] 1.000000
Is there a way to retrieve the sublist of my_dict corresponding to the "z" index?
(For instance, if my solution is x[18906,'C',2] 1.000000 then z = 2 and I want to obtain the sublist [4, 0, 0, 0])
Your code is not really a nice minimal example to work with, so it's hard to post valid code.
The general problem does not look that tough.
If your original dict looks like:
{(15687, 'B'): [[7, 0, 0, 0], [0, 7, 0, 0], [0, 0, 7, 0], [0, 0, 0, 7]],
...
(18906, 'C'): [[4, 0, 0, 3], [3, 0, 0, 3], [4, 0, 0, 0], [3, 0, 0, 0]}
and your solution is my_dict_opt, probably something like this should do (python3):
import numpy as np # easy fp-math comparison
sublists = []
for key, val in my_dict.items():
n_vars = len(val) # my assumption
for i in range(n_vars):
if np.isclose(my_dict_opt[key + tuple([i])].X, 1.0): # depends on your dict if .X is needed
sublists.append(my_dict[key][i])
Because of the dicts, the order of elements in sublists is not defined and this should only be a prototype as it's not really clear to me how those dicts are in use for you.

Permute rows and columns of a matrix

Assuming that I have the following matrix/array:
array([[0, 0, 1, 1, 1],
[0, 0, 1, 0, 1],
[1, 1, 0, 1, 1],
[1, 0, 1, 0, 0],
[1, 1, 1, 0, 0]])
and I want to apply the following permutation:
1 -> 5
2 -> 4
the result should be in the end:
array([[1, 1, 1, 0, 0],
[1, 0, 1, 0, 0],
[1, 1, 0, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1]])
Now, an incredibly naive (and memory costly) way of doing so might be:
a2 = deepcopy(a1)
a2[0,:] = a1[4,:]
a2[4,:] = a1[0,:]
a = deepcopy(a2)
a2[:,0] = a[:,4]
a2[:,4] = a[:,0]
a3 = deepcopy(a2)
a2[1,:] = a3[3,:]
a2[3,:] = a3[1,:]
a = deepcopy(a2)
a2[:,1] = a[:,3]
a2[:,3] = a[:,1]
But, I would like to know if there is something more efficient that does this. numpy.shuffle and numpy.permutation seem to permute only the rows of the matrix (not the columns at the same time). That doesn't work for me because the matrices are adjacency matrices (representing graphs), and I need to do the permutations which will give me a graph which is isomorphic with the original graph. Furthermore, I need to do an arbitrary number of permutations (more than one).
Thanks!
You can perform the swap in a one-liner using integer array indexing:
a = np.array([[0, 0, 1, 1, 1],
[0, 0, 1, 0, 1],
[1, 1, 0, 1, 1],
[1, 0, 1, 0, 0],
[1, 1, 1, 0, 0]])
b = a.copy()
# map 0 -> 4 and 1 -> 3 (N.B. Python indexing starts at 0 rather than 1)
a[[4, 3, 0, 1]] = a[[0, 1, 4, 3]]
print(repr(a))
# array([[1, 1, 1, 0, 0],
# [1, 0, 1, 0, 0],
# [1, 1, 0, 1, 1],
# [0, 0, 1, 0, 1],
# [0, 0, 1, 1, 1]])
Note that array indexing always returns a copy rather than a view - there's no way to swap arbitrary rows/columns of an array without generating a copy.
In this particular case you could avoid the copy by using slice indexing, which returns a view rather than a copy:
b = b[::-1] # invert the row order
print(repr(b))
# array([[1, 1, 1, 0, 0],
# [1, 0, 1, 0, 0],
# [1, 1, 0, 1, 1],
# [0, 0, 1, 0, 1],
# [0, 0, 1, 1, 1]])
Update:
You can use the same indexing approach to swap columns.
c = np.arange(25).reshape(5, 5)
print(repr(c))
# array([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19],
# [20, 21, 22, 23, 24]])
c[[0, 4], :] = c[[4, 0], :] # swap row 0 with row 4...
c[:, [0, 4]] = c[:, [4, 0]] # ...and column 0 with column 4
print(repr(c))
# array([[24, 21, 22, 23, 20],
# [ 9, 6, 7, 8, 5],
# [14, 11, 12, 13, 10],
# [19, 16, 17, 18, 15],
# [ 4, 1, 2, 3, 0]])
I've used a different example array in this case - your version will yield an identical output after performing the row/column swaps which makes it difficult to understand what's going on.
I found a solution to do what I want (though it is expensive):
a2 = deepcopy(a1)
first = randint(0, 5, 10)
second = randint(0, 5, 10)
for i in range(len(first)):
a = deepcopy(a2)
a2[first[i],:] = a[second[i],:]
a2[second[i],:] = a[first[i],:]
for i in range(len(first)):
a = deepcopy(a2)
a2[:,first[i]] = a[:,second[i]]
a2[:,second[i]] = a[:,first[i]]
Basically, I am doing 10 random switches. However, I need to copy the matrix many times. Anyway, a2 now represents a graph which is isomorphic with a1.

Creating lists from elements in a bigger list

I have a list whose size is a multiple of 16. What I want to do is go through the list and get 16 elements and create a list from those values, and then store those values somewhere. After that I can either ignore them or remove them from the list, and continue this process until the bigger list is empty. What I was trying to do was to go through the list, and keep a counter of some sort to keep track of the number of elements that have been appended to the list. However, I have been stuck from there. Any ideas on how to accomplish on what I am trying to do? Any ideas would be greatly appreciated.
lst = [[1, 4, 0], [2, 4, 0], [3, 4, 0], [4, 4, 0], [1, 3, 0], [2, 3, 0], [3, 3, 0], [4, 3, 0], [1, 2, 0], [2, 2, 0], [3, 2, 0], [4, 2, 0], [1, 1, 0], [2, 1, 0], [3, 1, 0], [4, 1, 0],[1, 4, 0], [2, 4, 0], [3, 4, 0], [4, 4, 0], [1, 3, 0], [2, 3, 0], [3, 3, 0], [4, 3, 0], [1, 2, 0], [2, 2, 0], [3, 2, 0], [4, 2, 0], [1, 1, 0], [2, 1, 0], [3, 1, 0], [4, 1, 0]]
If I understand you correctly, you start with a list of size n, where n % 16 == 0. You want to end with n/16 lists of size 16. You can accomplish this pretty easily with a double for loop. The outer loop should go for n/16 iterations. the inner loop should go for 16 iterations. The outer loop creates a new list with each iteration. the inner loop takes elements from the original list and appends them to the newly created list.
Thank you for taking the time to respond to my question. After clicking on random links on the right hand side I came to answer that did exactly what I needed to happen.
Here is the solution to my problem:
[input[i:i+n] for i in range(0, len(input), n)]
The solution above goes through input and creates a list of size n.