How to create list of array combinations lexographically in numpy? - python

I have this array and I want to return unique array combinations. I tried meshgrid but it creates duplicates and inverse array values
>> import numpy as np
>> array = np.array([0,1,2,3])
>> combinations = np.array(np.meshgrid(array, array)).T.reshape(-1,2)
>> print(combinations)
[[0 0]
[0 1]
[0 2]
[0 3]
[1 0]
[1 1]
[1 2]
[1 3]
[2 0]
[2 1]
[2 2]
[2 3]
[3 0]
[3 1]
[3 2]
[3 3]]
What I want to exclude are the repeating arrays: [0,0] [1,1] [2,2] [3,3] and the inverse arrays when [2,3] is returned exclude [3,2] in the output.
Take a look at this combination calculator, this is the output that I like but how can I create it in NumPy?

you could use combinations from itertools
import numpy as np
from itertools import combinations
array = np.array([0,1,2,3])
combs = np.array(list(combinations(arr, 2)))

Related

Generating Combinatorics With Numpy

I am trying to implement a quick tool to find the combinations of a set of numbers (0...k), for j lots of this array, where the sum across the row is equal to k-j, and k>=j
For instance, for k=3, and j=2, I have all the following combinations:
[[0 0]
[0 1]
[0 2]
[1 0]
[1 1]
[1 2]
[2 0]
[2 1]
[2 2]]
There are only two elements that sum up to k-j=1:
[[0 1]
[1 0]]
My current implementation is slow as I approach high numbers of k and j:
from itertools import product
from numpy import
combs = np.array(list(product(np.arange(0, k), repeat=j)))
combs = combs[np.sum(combs, axis=1)==k-j]
print(combs)
Can anyone please suggest a more efficient algorithm than I have at the moment?
For one, you don't have to consider the range up to k, but only up to k-j. Further, you could use itertools.combinations (if you are only interested in the set and not the order), as follows:
combs = np.array(list(combinations(range(k-j+1), j)))
combs = combs[np.sum(combs, axis=1)==k-j]

Loop through rows of input matrices with vectorize

I have a 4x2 and a 2x2 matrices. I would like to loop each combination of rows (vectors of dimension 2) through a function foo using vectorize.
Here are the matrices:
X = np.array([[1, 0], [2, 0], [3, 0], [4,0]])
Y = np.array([[1, 0], [2, 0]])
Here's how I'm trying to run it:
def foo(x, y):
print("inputs:", x, y)
return x[0] * y[0]
bar = np.vectorize(foo, signature="???")
output = bar(X, Y)
print(output)
I'm looking for the following output. bar would return a 4x2 matrice:
inputs: [1,0] [1,0]
inputs: [1,0] [2,0]
inputs: [2,0] [1,0]
inputs: [2,0] [2,0]
inputs: [3,0] [1,0]
inputs: [3,0] [2,0]
inputs: [4,0] [1,0]
inputs: [4,0] [2,0]
[[1,2], [2,4], [3,6], [4,8]]
I've tried various combinations of signature, but I'm just not grokking how to use it given the output I'm looking for.
NB: I am aware vectorize just uses Python for loops under the hood and offers no performance benefit. I just want to understand how to use it.
The basic use of vectorize broadcasts the inputs against each other, and passes scalar tuples to your function. A (4,2) can't broadcast with a (2,2). signature is an addition that should make it possible to pass "rows" of your arrays. It's even slower, and I haven't see it used much (or recommended it).
In [536]: bar = np.vectorize(foo, signature="(n),(n)->()")
In [533]: bar(X,Y[0,:])
inputs: [1 0] [1 0]
inputs: [2 0] [1 0]
inputs: [3 0] [1 0]
inputs: [4 0] [1 0]
Out[533]: array([1, 2, 3, 4])
In [537]: bar(X[:,None],Y[None])
inputs: [1 0] [1 0]
inputs: [1 0] [2 0]
inputs: [2 0] [1 0]
inputs: [2 0] [2 0]
inputs: [3 0] [1 0]
inputs: [3 0] [2 0]
inputs: [4 0] [1 0]
inputs: [4 0] [2 0]
Out[537]:
array([[1, 2],
[2, 4],
[3, 6],
[4, 8]])
So this gives bar a (4,1,2) and (1,2,2); which broadcast as (4,2,2). Or with this signature it's broadcasting a (4,1) with 1,2) => (4,2). It's the signature that determines how the last dimensions match.
It may in some cases be convenient, but I wouldn't recommend devoting too much time to understanding vectorize.

Unique symmetrical elements Numpy Array

I have a Numpy array as this:
[1 4]
[2 3]
[3 0]
[4 1]
[5 6]
[6 5]
[7 6]]
This is output of NearestNeighbors algorithm of scikit-learn. I want to remove duplicated values. To have something like this:
[[0 3]
[1 4]
[2 3]
[6 5]
[7 6]]
I searched a lot, but not found any solution.
One way with sorting and np.unique -
np.unique(np.sort(a, axis=1), axis=0)

How to make a list of 2D 3x3 array and save the ndarray with numpy save?

So let's say I have some 3x3 matrix I get with a calculation I am doing, let's say
np.array([[1,2,3],[4,5,6],[7,8,9]])
np.array([[0,0,0],[0,0,0],[0,0,0]])
I want to add this onto some matrix A and be able to access them so that if I do
> A[0]
> [[1,2,3],[4,5,6],[7,8,9]]
> A[1]
> [[0,0,0],[0,0,0],[0,0,0]]
and keep adding on bunch of these 2D array and save them with np.save('A', A) for fast access later. I kind of saw it is possible with appending to a list but I can't save a list with np.save for fast efficient access. How can I create a empty ndarray I can add matrix onto and save it all as .npy?
You can convert list to array it is the same:
A = list()
A.append(x)
A.append(y)
X = np.array(A)
np.save('X', X)
Originally use this:
A = np.stack((a,b))
[[[1 2 3]
[4 5 6]
[7 8 9]]
[[0 0 0]
[0 0 0]
[0 0 0]]]
And once you have formed A, if you want to add another array c to A use:
A = np.vstack((A,[c]))
output for c=a:
[[[1 2 3]
[4 5 6]
[7 8 9]]
[[0 0 0]
[0 0 0]
[0 0 0]]
[[1 2 3]
[4 5 6]
[7 8 9]]]

Remove row from a numpy array according to some condition and concatenate result

I have a list of numpy arrays and I wanted to remove a row according to some condition.
Lets suppose I have the following list of numpy arrays and I want to delete the rows which contain an item that is > 8.
test = [np.array([[2,2,4],[10,3,5],[1,2,4,],[1,2,4]]),
np.array([[1,2,3],[1,3,5],[6,3,1],[9,1,2]])]
for i in test:
z = np.argwhere(i>8)
print(z)#[[1 0]] and [[3 0]]
a1 = np.delete(i,z,axis=0)
print(a1)
This for loop skips the numpy array of index[0]. How can Ifix this?
Returns:
[[1 2 4]
[1 2 4]]
[[1 3 5]
[6 3 1]]
Desirable Return:
[[2,2,4]
[1 2 4]
[1 2 4]]
[[1,2,3]
[1 3 5]
[6 3 1]]
From your example, you want to remove row with index 1 from the first array,
and row with index 3 from the second array.
So use those indices when executing np.delete:
a1 = np.delete(i, z[0][0], axis=0)
np.argwhere will return both indices, but we're only interested in the rows:
np.argwhere(i > 8)[:, 0]
But really, we're only interested in unique rows, so we can take care of that too:
np.unique(np.argwhere(i > 8)[:, 0])
Altogether we get:
test = [np.array([[2,2,4],[10,3,5],[1,2,4,],[1,2,4]]),np.array([[1,2,3],[1,3,5],[6,3,1],[9,1,2]])]
for i in test:
z = np.unique(np.argwhere(i>8)[:, 0])
a1 = np.delete(i,z,axis=0)
print(a1)
#[[2 2 4]
# [1 2 4]
# [1 2 4]]
#[[1 2 3]
# [1 3 5]
# [6 3 1]]

Categories