Appending elements with similar index in Python - python

I want to append elements of A (shape=(1,10,2)) with the same j to create a new array A1. For example, [1,3] and [2,3] should be appended into one element because of same j (=3) and different i (=1 and =2 respectively). The desired output is attached.
import numpy as np
A=np.array([[
[0, 1],
[0, 2],
[1, 3],
[2, 3],
[2, 4],
[3, 5],
[3, 6],
[4, 6],
[5, 7],
[6, 7]]])
The desired output is
A1=array([[
[0, 1],
[0, 2],
[[1, 3],[2, 3]],
[2, 4],
[3, 5],
[[3, 6],[4, 6]],
[[5, 7],[6, 7]]]])
A1.shape=(1,7,2)

I've done it using the following steps. The only problem is that you can't have the final result as an array because of varying sizes. If you convert the result to a numpy array it becomes an array of lists of shape (7,).
You can however still iterate through it with for loops if it's not a huge list.
If you are using it in neural networks, you might want to consider converting to a ragged tensor
Get the list of second numbers
second_numbers = A[:,:,1].reshape(-1)
Get unique values from that list
uniq = set(second_numbers)
Create new list based on those unique values
new_list = []
for i in uniq:
new_list.append((A[:, second_numbers == i, :].reshape(-1,2)).tolist())
Full code with result:
second_numbers = A[:,:,1].reshape(-1)
uniq = set(second_numbers)
new_list = []
for i in uniq:
new_list.append((A[:, second_numbers == i, :].reshape(-1,2)).tolist())
new_list
>>> [[[0, 1]],
[[0, 2]],
[[1, 3], [2, 3]],
[[2, 4]],
[[3, 5]],
[[3, 6], [4, 6]],
[[5, 7], [6, 7]]]

Related

How to sum vector arrays in a list of lists?

I want to sum a list of vectors in a list while keeping their dimension and list structure. How can this be done?
Given a vector
vecs = [[[1, 1], [2, 2], [3, 3], [4, 4]],[[5, 5], [6, 6], [7, 7],[8, 8]]]
and the expected output is
vecs_sum = [[10,10],[26,26]]
I tried the following, but it just returns [].
vec_sum = []
for inner_list in vec_sum:
temp = []
for arr in inner_list:
temp = [sum(x) for x in zip(arr)]
vec_sum.append(temp)
This is one approach using a list comprehension
Ex:
vecs = [[[1, 1], [2, 2], [3, 3], [4, 4]],[[5, 5], [6, 6], [7, 7],[8, 8]]]
vecs_sum = [list(map(sum, zip(*i))) for i in vecs]
print(vecs_sum)
Output:
[[10, 10], [26, 26]]

Comprehension with chained for statements

So I am supposed to take an array x and an array y, and make a new array of pairs such that the elements are not equal. Here is my code:
x=[1,2,3,4]
y=[2,4,6]
my_list=[]
for a in x:
for b in y:
if a!=b:
list=[a,b]
my_list.append(list)
#my_list+=[(a,b) for (a,b) in (x,y) if (a!=b)]
print (my_list)
Thus, the output is: [[1, 2], [1, 4], [1, 6], [2, 4], [2, 6], [3, 2], [3, 4], [3, 6], [4, 2], [4, 6]]
Without importing anything, how do I collapse this with list comprehension AND chained for statements. My meager attempt is in the #comment section.
Here's how you can do it using a list comprehension:
x=[1,2,3,4]
y=[2,4,6]
[[a,b] for a in x for b in y if a!=b]
Output
[[1, 2], [1, 4], [1, 6], [2, 4], [2, 6], [3, 2], [3, 4], [3, 6], [4, 2], [4, 6]]
You can also avoid creating x and y variables by writing the following code
[[i, j] for i in [1, 2, 3, 4] for j in [2, 4, 6] if i != j]
This is also a where you can make use of itertools to build the output. Gets you the same output as a list comprehension, but with a little less code.
import itertools
x=[1,2,3,4]
y=[2,4,6]
list(itertools.product(x, y))

numpy array max min from pixelpoints of open cv [duplicate]

I have a large n x 2 numpy array that is formatted as (x, y) coordinates. I would like to filter this array so as to:
Identify coordinate pairs with duplicated x-values.
Keep only the coordinate pair of those duplicates with the highest y-value.
For example, in the following array:
arr = [[1, 4]
[1, 8]
[2, 3]
[4, 6]
[4, 2]
[5, 1]
[5, 2]
[5, 6]]
I would like the result to be:
arr = [[1, 8]
[2, 3]
[4, 6]
[5, 6]]
Ive explored np.unique and np.where but cannot figure out how to leverage them to solve this problem. Thanks so much!
Here's one way based on np.maximum.reduceat -
def grouby_maxY(a):
b = a[a[:,0].argsort()] # if first col is already sorted, skip this
grp_idx = np.flatnonzero(np.r_[True,(b[:-1,0] != b[1:,0])])
grp_maxY = np.maximum.reduceat(b[:,1], grp_idx)
return np.c_[b[grp_idx,0], grp_maxY]
Alternatively, if you want to bring np.unique, we can use it to find grp_idx with np.unique(b[:,0], return_index=1)[1].
Sample run -
In [453]: np.random.seed(0)
In [454]: arr = np.random.randint(0,5,(10,2))
In [455]: arr
Out[455]:
array([[4, 0],
[3, 3],
[3, 1],
[3, 2],
[4, 0],
[0, 4],
[2, 1],
[0, 1],
[1, 0],
[1, 4]])
In [456]: grouby_maxY(arr)
Out[456]:
array([[0, 4],
[1, 4],
[2, 1],
[3, 3],
[4, 0]])

List with 2 elements, a list and an int, want to relate every list item with that int

I have a list of lists in which every element of the first list is composed of a second list and an integer.
What I want to do is relate that single integer with every element in the list, thus making the elements of the first list be lists of 2 elements the code. I haven't got a clue on how to do this.
This is the code i'm using to test this:
list1 = [[1,2,3],[1,2,3,4]]
list2 = []
list3 = []
for element in range (len(list1)):
list2.append(list1[element][0])
list2.append(list3)
list3.append([list1[element][1:]])
list3[element].append(list1[element][0])
print(list3)
A simple approach for your first example:
l = [1,[2,3]]
final_l = [[l[0], i] for i in l[-1]]
Output:
[[1, 2], [1, 3]]
A solution for a larger example:
l = [[1,[2,3]], [3, [45, 2]], [6, [12, 2]], [3, [3, 4]]]
final_l = [[[c, a] for c in b] for a, b in l]
Output:
[[[2, 1], [3, 1]], [[45, 3], [2, 3]], [[12, 6], [2, 6]], [[3, 3], [4, 3]]]
Try this:
list2 = [[[l[0], num] for num in l[1:]] for l in list1]
The output is:
list2 = [[[1, 2], [1, 3]], [[1, 2], [1, 3], [1, 4]]]
You can try in one line with this approach:
l = [[1,[2,3]], [3, [45, 2]], [6, [12, 2]], [3, [3, 4]]]
print(list(map(lambda x:list(map(lambda y:[y,x[0]],x[1])),l)))
output:
[[[2, 1], [3, 1]], [[45, 3], [2, 3]], [[12, 6], [2, 6]], [[3, 3], [4, 3]]]

How to remove duplicates from a 3D array in Python?

I have a 3D array as follow, 'b', which I want to represent an array of 2-D array. I want to remove the duplicates of my 2-D arrays and get the unique ones.
>>> a = [[[1, 2], [1, 2]], [[1, 2], [4, 5]], [[1, 2], [1, 2]]]
>>> b = numpy.array(a)
>>> b
array([[[1, 2],
[1, 2]],
[[1, 2],
[4, 5]],
[[1, 2],
[1, 2]]])
In this above example, I really want to return the following because there exist one duplicate which I want to remove.
unique = array([[[1, 2],
[1, 2]],
[[1, 2],
[4, 5]])
How should do this with numpy package? Thanks
See previous answer: Remove duplicate rows of a numpy array
convert to array of tuples and then apply np.unique()
Converting to tuple and back again is probably going to be quire expensive, instead you can do a generalized view:
def unique_by_first(a):
tmp = a.reshape(a.shape[0], -1)
b = np.ascontiguousarray(tmp).view(np.dtype((np.void, tmp.dtype.itemsize * tmp.shape[1])))
_, idx = np.unique(b, return_index=True)
return a[idx].reshape(-1, *a.shape[1:])
Usage:
print unique_by_first(a)
[[[1 2]
[1 2]]
[[1 2]
[4 5]]]
Effectively, a generalization of previous answers.
You can convert each such 2D slice off the last two axes into a scalar each by considering them as indices on a multi-dimensional grid. The intention is to map each such slice to a scalar based on their uniqueness. Then, using those scalars, we could use np.unique to keep one instance only.
Thus, an implementation would be -
idx = np.ravel_multi_index(a.reshape(a.shape[0],-1).T,a.max(0).ravel()+1)
out = a[np.sort(np.unique(idx, return_index=1)[1])]
Sample run -
In [43]: a
Out[43]:
array([[[8, 1],
[2, 8]],
[[3, 8],
[3, 4]],
[[2, 4],
[1, 0]],
[[3, 0],
[4, 8]],
[[2, 4],
[1, 0]],
[[8, 1],
[2, 8]]])
In [44]: idx = np.ravel_multi_index(a.reshape(a.shape[0],-1).T,a.max(0).ravel()+1)
In [45]: a[np.sort(np.unique(idx, return_index=1)[1])]
Out[45]:
array([[[8, 1],
[2, 8]],
[[3, 8],
[3, 4]],
[[2, 4],
[1, 0]],
[[3, 0],
[4, 8]]])
If you don't mind the order of such slices being maintained, skip the np.sort() at the last step.
Reshape, find the unique rows, then reshape again.
Finding unique tuples by converting to a set.
import numpy as np
a = [[[1, 2], [1, 2]], [[1, 2], [4, 5]], [[1, 2], [1, 2]]]
b = np.array(a)
new_array = [tuple(row) for row in b.reshape(3,4)]
uniques = list(set(new_array))
output = np.array(uniques).reshape(len(uniques), 2, 2)
output
Out[131]:
array([[[1, 2],
[1, 2]],
[[1, 2],
[4, 5]]])

Categories