how to generate all possible pairs of coordinates without repetition in numpy efficiently

  • Last Update :
  • Techknowledgy :

Here is a straightforward numpy method, not sure how fast it is:

shape = 10, 10, 3
np.stack([ * map(np.transpose, map(np.unravel_index, np.triu_indices(np.prod(shape), 1), 2 * (shape, )))], -2)

Output:

array([
   [
      [0, 0, 0],
      [0, 0, 1]
   ],

   [
      [0, 0, 0],
      [0, 0, 2]
   ],

   [
      [0, 0, 0],
      [0, 1, 0]
   ],

   ...,

   [
      [9, 9, 0],
      [9, 9, 1]
   ],

   [
      [9, 9, 0],
      [9, 9, 2]
   ],

   [
      [9, 9, 1],
      [9, 9, 2]
   ]
])

Update: Same idea, same result but faster

np.column_stack(np.unravel_index(np.arange(np.prod(shape)), shape))[np.column_stack(np.triu_indices(np.prod(shape), 1))]

Below example is cooler but slower than OP's solution :(

% % timeit
first_pix = []
second_pix = []
for i in range(len(pixels)):
   first = pixels[i]
for j in pixels[i + 1: ]:
   second = j
first_pix.append(first)
second_pix.append(second)

3.57 ms ± 59.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) ​

% % timeit
mixed = {
   frozenset((i, j)) for i in pixels
   for j in pixels
   if i != j
}

Create a list of all pixels, but we use tuples so they are hashable. We will see why later.

img_width = 10
img_height = 10
img_colors = 3

pixels = [(x, y, c) for x in range(img_width) for y in range(img_height) for c in range(3)]

Now we check that it has the correct number of values:

>>> desired_length = (len(pixels) * (len(pixels) - 1)) / 2 >>>
   assert len(mixed) == desired_length
True

We use a 2 dimensional set comprehension to create permutations. It has the following format:

{
   (x, y) for x in xs
   for y in ys
}

Suggestion : 2

Here is a straightforward numpy method, anycodings_combinations not sure how fast it is:,It's a bit crude , but for reference this is anycodings_numpy how i do this now:,all_pixels = np.array(np.meshgrid(range(10), anycodings_numpy range(10), range(3))).T.reshape(-1, 3),Now we check that it has the correct anycodings_combinations number of values:

It's a bit crude , but for reference this is anycodings_numpy how i do this now:

    start = time.time()
    x, y, z = shape
    all_pixels = []
    for i in range(x):
       for j in range(y):
       if z > 1:
       for k in range(z):
       all_pixels.append([i, j, k])
    else:
       all_pixels.append([i, j])
    first_pix = []
    second_pix = []
    for i in range(len(all_pixels)):
       first = all_pixels[i]
    for j in all_pixels[i + 1: ]:
       second = j
    first_pix.append(first)
    second_pix.append(second)
    print("generation of pixels took " + str(time.time() - start))
    return np.array(first_pix), np.array(second_pix)

Here is a straightforward numpy method, anycodings_combinations not sure how fast it is:

shape = 10, 10, 3
np.stack([ * map(np.transpose, map(np.unravel_index, np.triu_indices(np.prod(shape), 1), 2 * (shape, )))], -2)

Output:

array([
   [
      [0, 0, 0],
      [0, 0, 1]
   ],

   [
      [0, 0, 0],
      [0, 0, 2]
   ],

   [
      [0, 0, 0],
      [0, 1, 0]
   ],

   ...,

   [
      [9, 9, 0],
      [9, 9, 1]
   ],

   [
      [9, 9, 0],
      [9, 9, 2]
   ],

   [
      [9, 9, 1],
      [9, 9, 2]
   ]
])

Update: Same idea, same result but anycodings_combinations faster

np.column_stack(np.unravel_index(np.arange(np.prod(shape)), shape))[np.column_stack(np.triu_indices(np.prod(shape), 1))]

Below example is cooler but slower than OP's solution :(

% % timeit
first_pix = []
second_pix = []
for i in range(len(pixels)):
   first = pixels[i]
for j in pixels[i + 1: ]:
   second = j
first_pix.append(first)
second_pix.append(second)

3.57 ms ± 59.7 µs per loop anycodings_combinations (mean ± std. dev. of 7 runs, 100 anycodings_combinations loops each) ​

% % timeit
mixed = {
   frozenset((i, j)) for i in pixels
   for j in pixels
   if i != j
}

Create a list of all pixels, but we use anycodings_combinations tuples so they are hashable. We will see anycodings_combinations why later.

img_width = 10
img_height = 10
img_colors = 3

pixels = [(x, y, c) for x in range(img_width) for y in range(img_height) for c in range(3)]

Now we check that it has the correct anycodings_combinations number of values:

>>> desired_length = (len(pixels) * (len(pixels) - 1)) / 2 >>>
   assert len(mixed) == desired_length
True

We use a 2 dimensional set comprehension anycodings_combinations to create permutations. It has the anycodings_combinations following format:

{
   (x, y) for x in xs
   for y in ys
}

Suggestion : 3

I am trying to generate all pairs of coordinates for pixels in an image with colors, without the pairs repeating (order doesn't matter, so ((1,1,1), (2,2,2) is the same as ((2,2,2), (1,1,1)) and we want to include this pair only once). Also it's important to me that the coordinates are stored in a numpy array. ,but that's because we don't have to consider repetitions. Doing that but trying to create pairs of pixels gives me duplicates. I guess i could remove duplicates in some smart way but i have no idea how to do it in an efficient way.,Let's assume i have a 10x10 image. This means that the image has 100 pixels with 3 color channels what equals to 300 coordinates. This gives us 300*299/2 unique pairs of coordinates. Both using itertools.combinations() or normal python iteration , and then converting to np.array, is painstakingly slow with bigger images (on my pc for 32x32x3 image it takes 5s).,→ Put a Rendered Django Template in Json along with some other items

It's a bit crude , but for reference this is how i do this now:

    start = time.time()
    x, y, z = shape
    all_pixels = []
    for i in range(x):
       for j in range(y):
       if z > 1:
       for k in range(z):
       all_pixels.append([i, j, k])
    else:
       all_pixels.append([i, j])
    first_pix = []
    second_pix = []
    for i in range(len(all_pixels)):
       first = all_pixels[i]
    for j in all_pixels[i + 1: ]:
       second = j
    first_pix.append(first)
    second_pix.append(second)
    print("generation of pixels took " + str(time.time() - start))
    return np.array(first_pix), np.array(second_pix)

Here is a straightforward numpy method, not sure how fast it is:

shape = 10, 10, 3
np.stack([ * map(np.transpose, map(np.unravel_index, np.triu_indices(np.prod(shape), 1), 2 * (shape, )))], -2)

Output:

array([
   [
      [0, 0, 0],
      [0, 0, 1]
   ],

   [
      [0, 0, 0],
      [0, 0, 2]
   ],

   [
      [0, 0, 0],
      [0, 1, 0]
   ],

   ...,

   [
      [9, 9, 0],
      [9, 9, 1]
   ],

   [
      [9, 9, 0],
      [9, 9, 2]
   ],

   [
      [9, 9, 1],
      [9, 9, 2]
   ]
])

Update: Same idea, same result but faster

np.column_stack(np.unravel_index(np.arange(np.prod(shape)), shape))[np.column_stack(np.triu_indices(np.prod(shape), 1))]

Suggestion : 4

Given a list. The task is to write a Python program to get all pairwise combinations from the list.,Writing code in comment? Please use ide.geeksforgeeks.org, generate link and share the link here.,Python program to convert a list to string,However, the permutations’ method doesn’t distinguish between (a, b) and (b, a) pairs and returns them both. The itertools library also supports a combinations() method that prints either of the (a, b) or (b, a) pairs and not both. The output number of elements is equivalent to (n-1)! where n is the length of the list. The time required to compute combinations is roughly polynomial. 

Python provides support of itertools standard library which is used to create iterators for efficient looping. The library provides support for various kinds of iterations, in groups, sorted order, etc. The permutations() functions of this library are used to get through all possible orderings of the list of elements, without any repetitions. The permutations() functions have the following syntax:

itertools.permutations(lst, r)

Output :

(2, 2)
(2, 2)
(2, 2)
(2, 2)
(2, 2)
(2, 2)

Suggestion : 5

The easiest way to create an array is to use the array function. This accepts any sequence-like object (including other arrays) and produces a new NumPy array containing the passed data. For example, a list is a good candidate for conversion:,Whenever you see “array”, “NumPy array”, or “ndarray” in the text, with few exceptions they all refer to the same thing: the ndarray object.,NumPy array indexing is a rich topic, as there are many ways you may want to select a subset of your data or individual elements. One-dimensional arrays are simple; on the surface they act similarly to Python lists:,As a simple example, suppose we wished to evaluate the function sqrt(x^2 + y^2) across a regular grid of values. The np.meshgrid function takes two 1D arrays and produces two 2D matrices corresponding to all pairs of (x, y) in the two arrays:

In[13]: data1 = [6, 7.5, 8, 0, 1]

In[14]: arr1 = np.array(data1)

In[15]: arr1
Out[15]: array([6., 7.5, 8., 0., 1.])
In[27]: arr1 = np.array([1, 2, 3], dtype = np.float64)

In[28]: arr2 = np.array([1, 2, 3], dtype = np.int32)

In[29]: arr1.dtype In[30]: arr2.dtype
Out[29]: dtype('float64') Out[30]: dtype('int32')
In[45]: arr = np.array([
   [1., 2., 3.],
   [4., 5., 6.]
])

In[46]: arr
Out[46]:
   array([
      [1., 2., 3.],
      [4., 5., 6.]
   ])

In[47]: arr * arr In[48]: arr - arr
Out[47]: Out[48]:
   array([
      [1., 4., 9.], array([
         [0., 0., 0.],
         [16., 25., 36.]
      ])[0., 0., 0.]
   ])
In[51]: arr = np.arange(10)

In[52]: arr
Out[52]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In[53]: arr[5]
Out[53]: 5

In[54]: arr[5: 8]
Out[54]: array([5, 6, 7])

In[55]: arr[5: 8] = 12

In[56]: arr
Out[56]: array([0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
In[75]: arr[1: 6]
Out[75]: array([1, 2, 3, 4, 64])
In[83]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])

In[84]: data = np.random.randn(7, 4)

In[85]: names
Out[85]:
   array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'],
      dtype = '|S4')

In[86]: data
Out[86]:
   array([
      [-0.048, 0.5433, -0.2349, 1.2792],
      [-0.268, 0.5465, 0.0939, -2.0445],
      [-0.047, -2.026, 0.7719, 0.3103],
      [2.1452, 0.8799, -0.0523, 0.0672],
      [-1.0023, -0.1698, 1.1503, 1.7289],
      [0.1913, 0.4544, 0.4519, 0.5535],
      [0.5994, 0.8174, -0.9297, -1.2564]
   ])

Suggestion : 6

r-length tuples, all possible orderings, no repeated elements,r-length tuples, in sorted order, no repeated elements,The permutation tuples are emitted in lexicographic ordering according to the order of the input iterable. So, if the input iterable is sorted, the combination tuples will be produced in sorted order.,The code for combinations() can be also expressed as a subsequence of permutations() after filtering entries where the elements are not in sorted order (according to their position in the input pool):

def accumulate(iterable, func = operator.add, *, initial = None):
   'Return running totals'
# accumulate([1, 2, 3, 4, 5]) -- > 1 3 6 10 15
# accumulate([1, 2, 3, 4, 5], initial = 100) -- > 100 101 103 106 110 115
# accumulate([1, 2, 3, 4, 5], operator.mul) -- > 1 2 6 24 120
it = iter(iterable)
total = initial
if initial is None:
   try:
   total = next(it)
except StopIteration:
   return
yield total
for element in it:
   total = func(total, element)
yield total
>>> data = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8] >>>
   list(accumulate(data, operator.mul)) # running product[3, 12, 72, 144, 144, 1296, 0, 0, 0, 0] >>>
   list(accumulate(data, max)) # running maximum[3, 4, 6, 6, 6, 9, 9, 9, 9, 9]

# Amortize a 5 % loan of 1000 with 4 annual payments of 90 >>>
   cashflows = [1000, -90, -90, -90, -90] >>>
   list(accumulate(cashflows, lambda bal, pmt: bal * 1.05 + pmt))[1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]

# Chaotic recurrence relation https: //en.wikipedia.org/wiki/Logistic_map
   >>>
   logistic_map = lambda x, _: r * x * (1 - x) >>>
   r = 3.8 >>>
   x0 = 0.4 >>>
   inputs = repeat(x0, 36) # only the initial value is used >>>
   [format(x, '.2f') for x in accumulate(inputs, logistic_map)]
   ['0.40', '0.91', '0.30', '0.81', '0.60', '0.92', '0.29', '0.79', '0.63',
      '0.88', '0.39', '0.90', '0.33', '0.84', '0.52', '0.95', '0.18', '0.57',
      '0.93', '0.25', '0.71', '0.79', '0.63', '0.88', '0.39', '0.91', '0.32',
      '0.83', '0.54', '0.95', '0.20', '0.60', '0.91', '0.30', '0.80', '0.60'
   ]
def chain( * iterables):
   # chain('ABC', 'DEF') -- > A B C D E F
for it in iterables:
   for element in it:
   yield element
def from_iterable(iterables):
   # chain.from_iterable(['ABC', 'DEF']) -- > A B C D E F
for it in iterables:
   for element in it:
   yield element
def combinations(iterable, r):
   # combinations('ABCD', 2) -- > AB AC AD BC BD CD
# combinations(range(4), 3) -- > 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
   return
indices = list(range(r))
yield tuple(pool[i]
   for i in indices)
while True:
   for i in reversed(range(r)):
   if indices[i] != i + n - r:
   break
else:
   return
indices[i] += 1
for j in range(i + 1, r):
   indices[j] = indices[j - 1] + 1
yield tuple(pool[i]
   for i in indices)
def combinations(iterable, r):
   pool = tuple(iterable)
n = len(pool)
for indices in permutations(range(n), r):
   if sorted(indices) == list(indices):
   yield tuple(pool[i]
      for i in indices)

Suggestion : 7

The ease of implementing mathematical formulas that work on arrays is one of the things that make NumPy so widely used in the scientific Python community.,NumPy gives you an enormous range of fast and efficient ways of creating arrays and manipulating numerical data inside them. While a Python list can contain different data types within a single list, all of the elements in a NumPy array should be homogeneous. The mathematical operations that are meant to be performed on arrays would be extremely inefficient if the arrays weren’t homogeneous.,An array is a central data structure of the NumPy library. An array is a grid of values and it contains information about the raw data, how to locate an element, and how to interpret an element. It has a grid of elements that can be indexed in various ways. The elements are all of the same type, referred to as the array dtype.,If you want to generate a list of coordinates where the elements exist, you can zip the arrays, iterate over the list of coordinates, and print them. For example:

conda install numpy
pip install numpy
import numpy as np
>>> a = np.arange(6) >>>
   a2 = a[np.newaxis,: ] >>>
   a2.shape(1, 6)
>>> a = np.array([1, 2, 3, 4, 5, 6])
>>> a = np.array([
   [1, 2, 3, 4],
   [5, 6, 7, 8],
   [9, 10, 11, 12]
])

Suggestion : 8

Let's use fancy indexing to select 20 random points. We'll do this by first choosing 20 random indices with no repeats, and use these indices to select a portion of the original array:,It is always important to remember with fancy indexing that the return value reflects the broadcasted shape of the indices, rather than the shape of the array being indexed.,Just as fancy indexing can be used to access parts of an array, it can also be used to modify parts of an array. For example, imagine we have an array of indices and we'd like to set the corresponding items in an array to some value:,Fancy indexing is conceptually simple: it means passing an array of indices to access multiple array elements at once. For example, consider the following array:

import numpy as np
rand = np.random.RandomState(42)

x = rand.randint(100, size = 10)
print(x)
[51 92 14 71 60 20 82 86 74 74]
[x[3], x[7], x[2]]
[71, 86, 14]
ind = [3, 7, 4]
x[ind]
array([71, 86, 60])