Find the indices of similar elements in numpy array - python

I have a numpy array that has different values in it some of which could be equal. I want to return a list of lists that each list contains the indices of equal elements. For example, imagine
A=np.array([2,3,2,1,1,1,3,4,5,6,6,6,6,3])
Then the result I want should be
[[0,2],[1,6,13],[3,4,5],[7],[8],[9,10,11,12]]
here is my solution but I am looking for a smarter way to do it:
h=[]
s=set()
for i in list_name:
if i in s:
continue
h.append(np.where(list_name==i))
s.add(i)
print h

Assuming the order doesn't matter, this should work.
import numpy as np
input_array = np.array([2,3,2,1,1,1,3,4,5,6,6,6,6,3])
out_array = [np.where(input_array == element)[0].tolist() for element in np.unique(input_array)]
When I run this, I get
[[3, 4, 5], [0, 2], [1, 6, 13], [7], [8], [9, 10, 11, 12]]

Try finding unique elements in the array using np.unique 1.
Loop over this array using np.where 2.
Example to find all indices with element 0 is
numpy.where(x == 0)[0]

You could use a hashmap. The key can be an int in the array, and the value can be a linked list that stores the indices of that int.
Loop through the array and for every int in the array, add its index to the hashmap.
At the end, retrieve those indices from the lists in the map.

A lookup table could do this nicely, then you can look them up explicitly:
mytable = {}
for i, value in enumerate(list_name):
mytable[value] = [i, *mytable.get(value,[])]
mytable.get(2)
[0,2]
And if you just want the indices, then:
indices = [mytable.get(a) for a in list_name]
[[0,2],[1,6,13],[3,4,5],[7],[8],[9,10,11,12]]

It's not a NumPy solution, but it does the trick (and applies to NumPy arrays too).
from collections import defaultdict
a = [2, 3, 2, 1, 1, 1, 3, 4, 5, 6, 6, 6, 6, 3]
positions = defaultdict(set)
for index, value in enumerate(a):
positions[value].add(index)
print(dict(positions))
outputs
{2: {0, 2}, 3: {1, 13, 6}, 1: {3, 4, 5}, 4: {7}, 5: {8}, 6: {9, 10, 11, 12}}

My attempt:
Kinda ugly having to do unique at the end but worked
import numpy as np
A=np.array([2,3,2,1,1,1,3,4,5,6,6,6,6,3])
def index(my_list, element):
return [i for i, x in enumerate(my_list) if x == element]
print np.unique(np.array([index(A,i) for i in A]))
>> [[0, 2] [1, 6, 13] [3, 4, 5] [7] [8] [9, 10, 11, 12]]

Related

Extract Lists from tuple with a condition

I was trying to extract lists from a tuple with a condition that every X numbers in ascending order should be extracted in same list, using a list comprehension.
Example:
Input: (4,2,2,3,5,6,0,0,2)
Desired output: [[4],[2,2,3,5,6],[0,0,2]]
I tried the following:
E=tuple([random.randint(0,10) for x in range(10)])
Res=[E[x:y] for x in range(0,len(E)) for y in range(x+1,len(E)) if (y>x)]
Here, simple logic to create new list already with the first element tuple. and then loop over tuple and if its current element is less then last element or not, if its smaller then append element as a list or append element into the last list.
Code:
import random
E=tuple([random.randint(0,10) for x in range(10)])
E
ls=[[E[0]]]
[ls.append([E[e]]) if E[e]<E[e-1] else ls[len(ls)-1].append(E[e]) for e in range(1, len(E)) ]
ls
OR Without pre-defining the first value
from itertools import pairwise
l=[[]]
[l[len(l)-1].append(y) if x-y < 0 else l.append([y]) for (x, y) in pairwise([e for e in (0,)+E])] ##Insert the dump 0 at first position
l
Input: (7, 10, 7, 2, 3, 7, 4, 3, 5, 10)
Output: [[7, 10], [7], [2, 3, 7], [4], [3, 5, 10]]
Input: (0, 3, 4, 3, 0, 7, 0, 0, 2, 3)
Output: [[0, 3, 4], [3], [0, 7], [0, 0, 2, 3]]
Here is one possible way to do this. You could use np.split together with random.sample to get the random numbers which is used as index to split.
import random
import numpy as np
lst = [4,2,2,3,5,6,0,0,2]
number_of_splits = 4
random.seed(42)
random_splits = sorted(random.sample(set(range(1,len(lst)-1)),number_of_splits-1))
print(random_splits)
result = [list(elem) for elem in np.split(lst, random_splits)]
print(result)
[1, 6, 7]
[[4], [2, 2, 3, 5, 6], [0], [0, 2]]
Probably easier to do this without a list comprehension - i.e., a straightforward loop like this:
from random import randint as RANDINT
t = 4, 2, 2, 3, 5, 6, 0, 0, 2
out = []
offset = 0
while offset < len(t):
e = RANDINT(1, len(t)+1-offset)
out.append(list(t[offset:offset+e]))
offset += e
print(out)
Output (example):
[[4], [2, 2], [3], [5, 6, 0, 0], [2]]
We can use slice to mark start and end of sub-lists
t=(4,2,2,3,5,6,0,0,2)
split_list=[0]+[x for x in range(len(t)) if t[x]<t[x-1]]
split_list_end=[x for x in range(len(t)) if t[x]<t[x-1]]
split_list_end.append(len(t))
[list(t[x]) for x in [slice(x[0],x[1]) for x in list(zip(split_list,split_list_end))]]

How to add elements of python lists in a dictionary

Below is list of arrays:
{'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
Code for array input:
def main():
a = int(input("Enter the number of array's: "))
size = int(input('Each array size: '))
arrays = dict()
for i in range(1, a + 1):
arrays['array_' + str(i)] = list(
map(lambda j: int(input('value: ')), [j for j in range(size)]))
print(arrays)
I want to add 'array_1' with array_2
Just for clarification, you have a dictionary of lists, not a list of arrays. I think this is what you're looking for
list_dict = {'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
[sum(items) for items in zip(list_dict['array_1'], list_dict['array_2'])]
this results in the list [4, 6, 8, 10] - I'm assuming that's what you mean by add array_1 and array_2
If by add you mean concatenate do this:
new_list = array['array_1'] + array['array_2']
else if you mean addition of individual values you can do:
from operator import add
new_array = list(map(add,array['array_1'],array['array_2']))
If you want to sum element wise then
d= {'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
[sum(x) for x in zip(*d.values())] # will add elements from all the lists
Output:
[11, 14, 17, 10]
going along the same lines if you just want to add lists corresponding to some keys then you can filter the keys to create a new dict and use it in a same way
[sum(x) for x in zip(*{key:value for key,value in d.items() if key in ['array_1','array_2']}.values())]
Output
[4, 6, 8, 10]

functions on arrays of different sizes in for loop

I have two arrays of different sizes that I want to perform logical functions on in a for loop. For example, if I have:
array1 = [6,7,8]
array2 = [1,2,3,4,5]
I want to do each element from array1 minus each element of array2 to get something like
[6-1,6-2,6-3,6-4,6-5],[7-1,7-2,7-3,7-4,7-5],[8-1,8-2,8-3,8-4,8-5]
which is subtracting each element from array2 from each element of array1
So i tried to do a for loop like:
for i in range(len(array1)):
ar = array1[i]-array2
and also
for i in range(len(array1)):
for j in range(len(array2)):
ar = array1[i]-array2[j]
But neither of these seem to be working
The first way seems to be returning an array of the right shape but certainly not the right values.
I'd like it to be returned in separate arrays because in reality, I have a very large sample size.
We can solve this using itertools.product
from itertools import product
from operator import sub
final = []
for item in array1:
prods = product([item], array2)
subs = [sub(*p) for p in prods]
final.append(subs)
print(final)
# [[5, 4, 3, 2, 1], [6, 5, 4, 3, 2], [7, 6, 5, 4, 3]]
How it works is product returns the cartesian product of the two arrays in the form of tuples, so:
(6, 1), (6, 2), etc....
Then we simply apply the sub function to each tuple using a list-comprehension.
The following solution should work using a list comprehension:
result = []
for value1 in array1:
result.append([value1 - value2 for value2 in array2])
You could even write this in 1 line using both for loops for the list comprehension:
result = [[value1 - value2 for value2 in array2] for value1 in array1]
Loops solution:
array1 = [6, 7, 8]
array2 = [1, 2, 3, 4, 5]
arr = []
for i in array1:
tmp = []
for j in array2:
tmp.append(i - j)
arr.append(tmp)
print(arr)
Output:
[[5, 4, 3, 2, 1], [6, 5, 4, 3, 2], [7, 6, 5, 4, 3]]
Your for loop is nearly correct except, you overwrite the value of ar every iteration (and you make it slightly more complicated with range)
You can achieve this through list comprehension
[[i - j for j in array2] for i in array1]
# [[5, 4, 3, 2, 1], [6, 5, 4, 3, 2], [7, 6, 5, 4, 3]]
You were on the right track but you had your arrays switched. You want array1 inside the inner loop to perform the operation you want to perform:
array1 = [6,7,8]
array2 = [1,2,3,4,5]
finalarray=[]
for i in range(len(array2)):
for j in range(len(array1)):
ar = array1[j]-array2[i]
finalarray.append(ar)
print(finalarray)
>>>[5, 6, 7, 4, 5, 6, 3, 4, 5, 2, 3, 4, 1, 2, 3]
ar is not being treated properly in your code, it needs to be an array of arrays (matrix) and you'll need another variable to hold the result per iteration, there's probably a better way to do this using list comprehensions but here is one way:
array1 = [6,7,8]
array2 = [1,2,3,4,5]
ar = []
row = []
for i in range(len(array1)):
for j in range(len(array2)):
row.append(array1[i]-array2[j])
ar.append(row)
row = []
print ar
There are plenty of good answers here, but another option especially useful for larger arrays is to use numpy, a package designed for moving large arrays of numbers efficiently. One possible answer in numpy would be this:
import numpy as np
array1 = np.arange(6,9) # make arrays 1 and 2
array2 = np.arange(1,6)
output = (array1.repeat(array2.shape[0]) # repeat array1 as many times as there are elements in array2
.reshape(array1.shape[0], -1) # reshape so we have a row for each element in array1
) - array2 # subtract array2 from each row
output
array([[5, 4, 3, 2, 1],
[6, 5, 4, 3, 2],
[7, 6, 5, 4, 3]])

convert multidimensional list into dictionary python

I'm working on a problem, and it would be much easier to solve if I had an elegant way to convert a multi dimensional list of n elements into a dictionary of keys corresponding with the index and values corresponding with the list values.
Example:
[[1,2,3],[4,5,6],[7,8,9]] => {0:[1,2,3], 1:[4,5,6], 2:[7,8,9]}
Is there a simple way to do this with Python?
To expand on my comment:
>>> array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> {index: list(value) for index, value in enumerate(array)}
{0: [1, 2, 3], 1: [4, 5, 6], 2: [7, 8, 9]}
changed value to list(value) to avoid byref v. byval issues
You can try using enumerate on the list:
new_dict = {}
for itr, ele in enumerate(array):
new_dict[itr] = ele
return new_dict
There may be another solution that is a little less code but this should work for what you are trying to do, assuming the index should be the key.
EDIT:
{itr: ele for itr, ele in enumerate(array)}
Some steps follow you can convert your any kind of multi dimensional list into dictionary
Step 1 :
call your list :
mylist = [[1,2,3],[4,5,6],[7,8,9]]
Step 2:
stored dict variable name
mydict = {}
for i in range(len(mylist)):
mydict[i] = mylist[i]
print(mydict)
Result :
{0: [1, 2, 3], 1: [4, 5, 6], 2: [7, 8, 9]}
[Note : The result is tested ]

Python - Remove a set of a list from another list

array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
array2 = [1, 2, 2, 2, 5, 6, 6, 6, 9]
temp = set(array2)
array1.remove(temp)
Traceback (most recent call last):
File "Sudoku V2.py", line 6, in <module>
array1.remove(temp)
ValueError: list.remove(x): x not in list
Try this:
array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
array2 = [1, 2, 2, 2, 5, 6, 6, 6, 9]
set(array1).difference(array2)
=> set([3, 4, 7, 8])
The above makes use of the difference() method of sets, which returns a new set with elements in the set that are not in the iterable(s) received as parameter. Notice that there's no need to convert array2 to a set for this to work.
Also be aware that by using sets, all duplicate elements will be removed and the original order of the iterables won't necessarily be preserved. If that's an issue, try this alternative solution:
[x for x in array1 if x not in array2]
=> [3, 4, 7, 8]
If you don't care about the order of elements in the result, or about duplicate elements, set.difference, as in Óscar López's answer, is exactly what you want.
If you do care about order and preserving duplicates, the simplest way is to just build a new list, filtering out the ones in array2:
set2 = set(array2)
array1 = [item for item in array1 if item not in set2]
If you need to destructively modify array1 in-place instead of building a new one, it's almost always simpler to just destructively replace the contents of array1 all at once:
array1[:] = [item for item in array1 if item not in set2]
If you really want to modify it element by element, the best way would be to iterate array1 backward, removing in-place:
set2 = set(array2)
for i, value in enumerate(array1)[::-1]:
if value in set2:
del array1[i]
Finally, you can do it the way flornquake suggested, but that will take quadratic time instead of linear, because it takes no advantage of the set; for each element in set2, it does a linear array1.remove.
Do you want array1 - array2?
set1 = set(array1)
set2 = set(array2)
set1.difference(set2) is what you want.
s -> sequence
s.remove(x) remove the first item from s where s[i] == x
remove raises ValueError when x is not found in s.
http://docs.python.org/3/library/stdtypes.html#index-23
None of the elements in array1 is a set. All the elements in array1 are integers.
The remove() method takes a single element of the list, so we have to call it once for each element:
for item in set(array2):
array1.remove(item)
Other methods such as Óscar's and abanert's are better though, they are more idiomatic and a lot more efficient.
This is three solution that can be help to your question:
array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
array2 = [1, 2, 2, 2, 5, 6, 6, 6, 9]
array = [i for i in array1 if i not in array2]
print(array)
o = list(set(array1) - set(array2))
print(o)
from collections import OrderedDict
p = OrderedDict()
p['array'] = list(set(array1) - set(array2))
print(*p.values())

Categories

Resources