I have a numpy array [0, 1, 1, 2, 2, 0, 1, ...] which only contains the numbers 0-k. I would like to create a new array that contains the n possible arrays of permutations of 0-k. A small example with k=2 and n=6:
a = [0, 1, 0, 2]
permute(a)
result = [[0, 1, 0, 2]
[0, 2, 0, 1]
[1, 0, 1, 2]
[2, 1, 2, 0]
[1, 2, 1, 0]
[2, 0, 2, 1]]
Does anyone have any ideas/solutions as to how one could achieve this?
Your a is what combinatorists call a multiset. The sympy library has various routines for working with them.
>>> from sympy.utilities.iterables import multiset_permutations
>>> import numpy as np
>>> a = np.array([0, 1, 0, 2])
>>> for p in multiset_permutations(a):
... p
...
[0, 0, 1, 2]
[0, 0, 2, 1]
[0, 1, 0, 2]
[0, 1, 2, 0]
[0, 2, 0, 1]
[0, 2, 1, 0]
[1, 0, 0, 2]
[1, 0, 2, 0]
[1, 2, 0, 0]
[2, 0, 0, 1]
[2, 0, 1, 0]
[2, 1, 0, 0]
if your permutations fit in the memory, you could store them in a set and thus only get the distinguishable permutations.
from itertools import permutations
a = [0, 1, 0, 2]
perms = set(permutations(a))
Related
Let's that we have geotiff of 0 and 1.
import rasterio
src = rasterio.open('myData.tif')
data = src.read(1)
data
array([[0, 1, 1, 0],
[1, 0, 0, 1],
[0, 0, 1, 0],
[1, 0, 1, 1]])
I would like to have for each pixel 1 the sum of all adjacent pixels forming a cluster of ones and to have something like the following:
array([[0, 2, 2, 0],
[1, 0, 0, 1],
[0, 0, 3, 0],
[1, 0, 3, 3]])
You can use scipy.ndimage.label:
from scipy.ndimage import label
out = np.zeros_like(data)
labels, N = label(data)
for i in range(N):
mask = labels==i+1
out[mask] = mask.sum()
output:
array([[0, 2, 2, 0],
[1, 0, 0, 1],
[0, 0, 3, 0],
[1, 0, 3, 3]])
I have a nested list that I want to do some data restructuring on. The nested list look like this:
[
[1, 2, 1, 0, 0],
[0, 1, 1, 0],
[1, 1, 0, 0, 0],
[0, 1, 1, 0],
[1, 1, 0, 0, 0],
[0, 1, 1, 1],
[1, 1, 0, 0, 0],
[0, 1, 1, 1],
[1, 1, 0, 0, 0],
[0, 1, 1, 1],
[0, 1, 2, 1],
[0, 1, 1, 1],
[1, 2, 1, 0, 0],
[2, 2, 1, 0, 0],
[0, 1, 2, 1],
[1, 2, 4, 2],
[0, 1, 2, 1]
]
I wrote a function to move that is supposed to either move the last element of the list to the front or add a 0 to the end of the list, depending on whether the length of the list is odd or even. This is the function I wrote:
def zero_move (list_obj):
if len(list_obj) % 2 != 0:
list_obj.insert(0, list_obj.pop())
else:
list_obj.append(0)
When I try to map the function to my nested lists it returns none values instead of new lists.
size_list = list(map(zero_move, sizes))
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
This is my desired outcome:
[0, 1, 2, 1, 0]
[0, 1, 1, 0, 0]
[0, 1, 1, 0, 0]
[0, 1, 1, 0, 0]
[0, 1, 1, 0, 0]
[0, 1, 1, 1, 0]
[0, 1, 1, 0, 0]
[0, 1, 1, 1, 0]
[0, 1, 1, 0, 0]
[0, 1, 1, 1, 0]
[0, 1, 2, 1, 0]
[0, 1, 1, 1, 0]
[0, 1, 2, 1, 0]
[0, 2, 2, 1, 0]
[0, 1, 2, 1, 0]
[1, 2, 4, 2, 0]
[0, 1, 2, 1, 0]
I don't understand why I am getting None back instead of my desired outcome.
This is because you are not returning anything. Both the insert and the append operations are modifying the original nested lists in-place. If we inspected the value of the original list after the map:
>>> list(map(zero_move, sizes)
[None, None, ...]
>>> sizes
[[0, 1, 2, 1, 0], [0, 1, 1, 0, 0], ...]
However, since the operation we are performing modifies the original list, it is more idiomatic to use a for loop instead of mapping over the list:
for s in sizes:
zero_move(s)
If however, you don't wish to modify the original list but rather return a new list reflecting the modifications, you will need to change your zero_move method to reflect that:
def zero_move_return(list_obj):
if len(list_obj) % 2 != 0:
return [list_obj[-1]] + list_obj[:-1]
else:
return [0] + list_obj
Now, if you apply your map, you will get the result you originally expected:
>>> list(map(zero_move_return, sizes))
[[0, 1, 2, 1, 0], [0, 1, 1, 0, 0], ...]
I'd need to know the most efficient way for the following case. There is a numpy.ndarray of shape 11k*11k for which I need to force all elements of some rows to be zero given a binary numpy array of shape 11k. A toy example could be described as follows:
Inputs:
x = np.array([[2, 1, 1, 2],
[0, 2, 1, 0],
[1, 0, 1, 1],
[2, 2, 1, 0]])
ref = np.array([0, 1, 1, 0])
Output:
y = ([[0, 0, 0, 0],
[0, 2, 1, 0],
[1, 0, 1, 1],
[0, 0, 0, 0]])
Use this -
y = np.multiply(x.T,ref).T
array([[0, 0, 0, 0],
[0, 2, 1, 0],
[1, 0, 1, 1],
[0, 0, 0, 0]])
this is my code:
import numpy as np
from scipy.ndimage.interpolation import shift
B = np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
F = np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 1],
[0, 0, 0, 0, 1],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
M = np.array([[1, 2, 1, 2, 1],
[1, 2, 1, 2, 1],
[1, 2, 1, 2, 0],
[1, 2, 1, 2, 1],
[1, 2, 1, 2, 1]])
if F[2, 4] == 1:
B = np.add(M, B)
if F[1, 4] == 1:
M_shift = shift(M, (-1, 0), cval=0)
B = np.add(M_shift, B)
print(B)
I want to add M to B if the condition for F is true. In this example both if-conditions are true and i thought that my code will add two times M to B. But apparently it's not working? What is wrong?
Thanks in advance.
EDIT for arra:
My desired output is in this case, my code snippet should add the matrix with B and also the shifted version of M. Because both conditions are True. But as u said the first assignment is overwritten. How can I prevent the overwriting for this case?
The output, after the assignment should look like this:
B = np.array([[2, 4, 2, 4, 2],
[2, 4, 2, 4, 1],
[2, 4, 2, 4, 1],
[2, 4, 2, 4, 2],
[1, 2, 1, 2, 1]])
I guess a good way is to use a for-loop because i want to check all array entries in Matrix F, if there's a 1. But i reckon that if i use the np.add function I'll overwrite it again
You overwrite B in the second if, so any previous value will be erased. Not sure what you are trying to achieve in your code, but don't you want something like:
B = np.add(M_shift, B)
or
intermediateVal = np.add(M_shift, F)
B = np.add(B, intermediateVal)
I'd like to find a value in a numpy array given a search pattern. For instance for the given array a, I want to retrieve a result of 1 when using the search pattern s because 1 is the element at index 0 of a[:,1] (=array([1, 0, 0, 1])) and the elements of a[1:,1] match s (i.e. (a[1:,1] == s).all() == True => return a[0,1]).
Another example would be s=[1, 0, 1] for which I would expect a search result of 2 (match at 4th column starting (1-based)). 2 would also be the search result for s=[2, 0, 0], etc.
>>> import numpy as np
>>> a = np.asarray([[0, 1, 2, 2, 2, 2, 2, 2], [0, 0, 1, 1, 2, 2, 3, 3], [0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0, 1]])
>>> a
array([[0, 1, 2, 2, 2, 2, 2, 2],
[0, 0, 1, 1, 2, 2, 3, 3],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 1, 0, 1]])
>>> s = np.asarray([0, 0, 1])
I came up with a[0, np.where((a[1:,:].transpose() == s).all(axis=-1))[0][0]], but thought there must be something more elegant...
Additionally, it would be great if I could do this operation with one call on multiple search patters, so that I retrieve the 0-element for which the values of index 1 to index 3 match.
Single search pattern
Here's one approach with help from broadcasting and slicing -
a[0,(a[1:] == s[:,None]).all(0)]
Multiple search patterns
For multiple search patterns (stored as 2D array), we just need to broadcast as before and look for ANY match at the end -
a[0,((a[1:] == s[...,None]).all(1)).any(0)]
Here's a sample run -
In [327]: a
Out[327]:
array([[0, 1, 2, 2, 2, 2, 2, 2],
[0, 0, 1, 1, 2, 2, 3, 3],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 1, 0, 1]])
In [328]: s
Out[328]:
array([[1, 0, 1],
[2, 0, 0]])
In [329]: a[0,((a[1:] == s[...,None]).all(1)).any(0)]
Out[329]: array([2, 2])