python munkres.py cost matrix - python

is it possible to allow munkres.py to accept a cost matrix that have more row than column? From it's code shown in github, it seems like it will only pad the row, when the cost matrix have more column than row.

It works either way. The source for the padding function is here.
You can verify it works both ways with this code:
>>> m = Munkres()
# 4 rows, 3 columns
>>> matrix = [[11, 12, 13], [21, 22, 23], [31, 32, 33], [41, 42, 43]]
>>> m.pad_matrix(matrix)
[[11, 12, 13, 0], [21, 22, 23, 0], [31, 32, 33, 0], [41, 42, 43, 0]]
# 3 rows, 4 columns
>>> matrix = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34]]
>>> m.pad_matrix(matrix)
[[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [0, 0, 0, 0]]

Related

Slicing non-continous indexes in 2d Numpy array

I have a matrix, i.e. 2D numpy array and would like to be able to slice out non-continuous parts of it. For example with the following matrix
[[11 12 13 14 15]
[21 22 23 24 25]
[31 32 33 34 35]
[41 42 43 44 45]
[51 52 53 54 55]]
i would like to be able to extract, say
[[11 12 14 15]
[21 22 24 25]
[51 52 54 55]]
Is there a way to do this?
I can easily extract continuous slice, for example matrix[0:2,0:3] would return
[[11 12 13]
[21 22 23]
but not sure how to extract non-continuous. I read about using np.r_[], which works if used on one dimension only, but not on both.
The solution would need to be scalable as well as it would have to be used on large matrices with many non-continuous indexes (which I was thinking would be passed as list).
You could use NumPy's advanced indexing and ix_() function to index the cross product of two 1-D sequences, the first one containing the indices of the rows you want to extract and the second one containing the indices of the columns.
In [24]: import numpy as np
In [25]: arr = np.asarray([[11, 12, 13, 14, 15],
...: [21, 22, 23, 24, 25],
...: [31, 32, 33, 34, 35],
...: [41, 42, 43, 44, 45],
...: [51, 52, 53, 54, 55]])
...:
In [26]: rows = [0, 1, 4]
In [27]: cols = [0, 1, 3, 4]
In [28]: arr[np.ix_(rows, cols)]
Out[28]:
array([[11, 12, 14, 15],
[21, 22, 24, 25],
[51, 52, 54, 55]])
It is worth pointing out that extending the approach above to index N-dimensional arrays is straightforward. You just need to pass further 1-D sequences to np.ix_.
You can used chained indexing:
arr = np.array([[11, 12, 13, 14, 15],
[21, 22, 23, 24, 25],
[31, 32, 33, 34, 35],
[41, 42, 43, 44, 45],
[51, 52, 53, 54, 55]])
In [28]: arr[[0,1,4]][:, [0,1,3,4]]
Out[28]:
array([[11, 12, 14, 15],
[21, 22, 24, 25],
[51, 52, 54, 55]])
You can do it like this and your list idea works perfectly with it. In delete, you can pass a list instead of just 2
q = np.array([[11, 12, 13, 14, 15],
[21, 22, 23, 24, 25],
[31, 32, 33, 34, 35],
[41, 42, 43, 44, 45],
[51, 52, 53, 54, 55]])
np.delete(q,2, axis=1)[np.array([0,1,4])]
array([[11, 12, 14, 15],
[21, 22, 24, 25],
[51, 52, 54, 55]])

More Pythonic / elegant way to fill a 2D array with sequences of integers?

I want to create a 6x6 numpy matrix, with the first row filled with: 0, 1, ..., 5, the second row filled with 10, 11, ... , 15, and the last row filled with 50, 51, ... , 55.
I thought about using (1) nested (two layer) list comprehensions, and then converting list-of-list into a numpy.matrix object, or (2) using variables inside of range function, i.e. - range(x) and vary x from 1 to 6. I was not able to get either of these two ideas to work.
Below is my non-vectorized / looping code to construct this matrix. Is there a more Pythonic way of doing this?
a = np.zeros((6,6))
for i in range(6):
for j in range(6):
a[i,j] = 10*i + j
print(a)
(This is one of the examples given at 39:00 in the intro video to NumPy on Youtube:
Intro to Numerical Computing with NumPy
How about np.ogrid?
np.add(*np.ogrid[:60:10, :6])
# array([[ 0, 1, 2, 3, 4, 5],
# [10, 11, 12, 13, 14, 15],
# [20, 21, 22, 23, 24, 25],
# [30, 31, 32, 33, 34, 35],
# [40, 41, 42, 43, 44, 45],
# [50, 51, 52, 53, 54, 55]])
Details
ogrid returns an open meshgrid:
a, b = np.ogrid[:60:10, :6]
a
# array([[ 0],
# [10],
# [20],
# [30],
# [40],
# [50]])
b
# array([[0, 1, 2, 3, 4, 5]])
You can then perform broadcasted addition:
# a + b
np.add(a, b)
# array([[ 0, 1, 2, 3, 4, 5],
# [10, 11, 12, 13, 14, 15],
# [20, 21, 22, 23, 24, 25],
# [30, 31, 32, 33, 34, 35],
# [40, 41, 42, 43, 44, 45],
# [50, 51, 52, 53, 54, 55]])
Similarly, you can also generate two ranges using np.arange and add them:
np.arange(0, 60, 10)[:,None] + np.arange(6)
# array([[ 0, 1, 2, 3, 4, 5],
# [10, 11, 12, 13, 14, 15],
# [20, 21, 22, 23, 24, 25],
# [30, 31, 32, 33, 34, 35],
# [40, 41, 42, 43, 44, 45],
# [50, 51, 52, 53, 54, 55]])
This can be accomplished with broadcasting,
arange(0, 6) + 10*arange(0, 6)[:, None]
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])
I'd recommend reading https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html and https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html. "Pythonic" doesn't really matter when working with numpy. Some times iterating, list comprehensions, and other pythonic approaches work well with arrays, other times they are terribly inefficient. However, the links given cover some high level concepts that are very powerfull with numpy.

numpy 3 dimension array middle indexing bug

I seems found a bug when I'm using python 2.7 with numpy module:
import numpy as np
x=np.arange(3*4*5).reshape(3,4,5)
x
Here I got the full 'x' array as follows:
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],
[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39]],
[[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49],
[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59]]])
Then I try to indexing single row values in sheet [1]:
x[1][0][:]
Result:
array([20, 21, 22, 23, 24])
But something wrong while I was try to indexing single column in sheet [1]:
x[1][:][0]
Result still be the same as previous:
array([20, 21, 22, 23, 24])
Should it be array([20, 25, 30, 35])??
It seems something wrong while indexing the middle index with range?
No, it's not a bug.
When you use [:] you are using slicing notation and it takes all the list:
l = ["a", "b", "c"]
l[:]
#output:
["a", "b", "c"]
and in your case:
x[1][:]
#output:
array([[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39]])
What you realy wish is using numpy indexing notation:
x[1, : ,0]
#output:
array([20, 25, 30, 35])
This is not a bug. x[1][:][0] is not a multiple index ("give me the elements where first dimension is 1, second is any, third is 0"). Instead, you are indexing three times, three objects.
x1 = x[1] # x1 is the first 4x5 subarray
x2 = x1[:] # x2 is same as x1
x3 = x2[0] # x3 is the first row of x2
To use multiple index, you want to do it in a single slice:
x[1, :, 0]

Python NumPy Convert Columns to Rows

Python 2.7.10 and NumPy. I have a matrix like this:
[[[ 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 25 26]
[27 28 29]
[30 31 32]
[33 34 35]]
[[36 37 38]
[39 40 41]
[42 43 44]
[45 46 47]]]
Note: The real matrix will have real data, and not consecutive numbers.
I need to rotate, flip, or something (I have tried them all) so as to end up with this:
[[[ 2 5 8 11]
[ 1 4 7 10]
[ 0 3 6 9]
[[14 17 20 23]
[13 16 19 22]
[12 15 18 21]
[[26 29 32 35]
[25 28 31 34]
[24 27 30 33]
[[38 41 44 47]
[37 40 43 46]
[36 39 42 45]]]
Basically, I need the entire columns of the matrix to become the rows.
Thanks.
Flip the positions of columns with [:,:,::-1] and use np.transpose to swap rows with columns -
In [25]: A
Out[25]:
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, 25, 26],
[27, 28, 29],
[30, 31, 32],
[33, 34, 35]]])
In [26]: A[:,:,::-1].transpose(0,2,1)
Out[26]:
array([[[ 2, 5, 8, 11],
[ 1, 4, 7, 10],
[ 0, 3, 6, 9]],
[[14, 17, 20, 23],
[13, 16, 19, 22],
[12, 15, 18, 21]],
[[26, 29, 32, 35],
[25, 28, 31, 34],
[24, 27, 30, 33]]])
Here's a simpler way to do it:
a=numpy.arange(48).reshape((4,4,3)
numpy.fliplr(a.swapaxes(1,2))
#or you could do
numpy.fliplr(a.transpose(0,2,1))
From what I can tell, flipud flips the last dimension, while fliplr flips the second to last dimension. In three dimensions, the last dimension is Z, while the second to last dimension is Y. Hence transposing the data, and flipping the Y dimension works.
Enjoy.
For each 2d subarray in your super-array you can apply the numpy function:
np.rot90() http://docs.scipy.org/doc/numpy/reference/generated/numpy.rot90.html
so:
import numpy as np
array= np.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, 25, 26],
[27, 28, 29],
[30, 31, 32],
[33, 34, 35]],
[[36, 37, 38],
[39, 40, 41],
[42, 43, 44],
[45, 46, 47]]])
desired_output = np.array([np.rot90(sub_array) for sub_array in array])
transpose and flipud are what you are looking for; the swapaxes can also function as transpose
Note that transpose has a version that operates on multiple dimensions.
There may be a simpler expression for this, but this has the advantage of not using elaborate indexing. Example, done in Python 2.7.3 with numpy
f=numpy.flipud
a=numpy.arange(48).reshape((4,4,3))
result=f(f(f(a).T).T).transpose(0,2,1)
In [2]: a=numpy.arange(48).reshape((4,4,3))
Out[3]:
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, 25, 26],
[27, 28, 29],
[30, 31, 32],
[33, 34, 35]],
[[36, 37, 38],
[39, 40, 41],
[42, 43, 44],
[45, 46, 47]]])
In [5]: f(f(f(a).T).T).transpose(0,2,1)
Out[5]:
array([[[ 2, 5, 8, 11],
[ 1, 4, 7, 10],
[ 0, 3, 6, 9]],
[[14, 17, 20, 23],
[13, 16, 19, 22],
[12, 15, 18, 21]],
[[26, 29, 32, 35],
[25, 28, 31, 34],
[24, 27, 30, 33]],
[[38, 41, 44, 47],
[37, 40, 43, 46],
[36, 39, 42, 45]]])
.

Move elements out of sublists into new list

I have a list that holds several sublist, each one of them with a given number of elements inside. I need to move all elements inside all sublists into another list, ie: remove the separation among elements imposed by the sublists.
This is a MWE if what I mean:
a = [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]], [[17, 18, 19, 20], [21, 22, 23, 24]], [[25, 26, 27, 28], [26, 30, 31, 32], [33, 34, 35, 36]]]
b = []
for elem in a:
for item in elem:
b.append(item)
which results in:
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24], [25, 26, 27, 28], [26, 30, 31, 32], [33, 34, 35, 36]]
I'm sure there's a more elegant and simpler way to do this in python.
Use itertools.chain.from_iterable:
>>> from itertools import chain
>>> list(chain.from_iterable(a))
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24], [25, 26, 27, 28], [26, 30, 31, 32], [33, 34, 35, 36]]
Timing comparison:
Try this:
[item for sublist in a for item in sublist]

Categories

Resources