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)
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'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]])
Here's a boolean array
In [102]: arr
Out[102]:
array([[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[1, 0, 0, 0],
[1, 0, 0, 0],
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[0, 0, 0, 1]], dtype=uint8)
And I want to compute the indices along axis-1 where there is an 1 and stop then and there and proceed with next column till I exhaust all columns. Thus, the expected solution would be:
array([ 1, 4, 5, 6, 0, 7, 8, 2, 9, 10, 3, 11, 12])
To explain a bit more about how the above result is desired: we start with column 1 and descend along axis-1 and we encounter 1 at index 1 and then again at index 4 and so on till where we encounter last 1 in that column at position 6. So, we stop there skipping rest of the column because there won't be any more 1s and then proceed to second column where we encounter 1 at index 0 and so on till we exhaust all columns. By putting together all indices we gathered so far should give us the result array.
I have a loopy solution but would very much prefer a vectorized one. How can we approach this? Any initial ideas would of great help.
In [134]: arr=np.array([[0, 1, 0, 0],
...: [1, 0, 0, 0],
...: [0, 0, 1, 0],
...: [0, 0, 0, 1],
...: [1, 0, 0, 0],
...: [1, 0, 0, 0],
...: [1, 0, 0, 0],
...: [0, 1, 0, 0],
...: [0, 1, 0, 0],
...: [0, 0, 1, 0],
...: [0, 0, 1, 0],
...: [0, 0, 0, 1],
...: [0, 0, 0, 1]], dtype=np.uint8)
Looks like where on the transpose finds the desired indices:
In [135]: np.where(arr.T)
Out[135]:
(array([0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]),
array([ 1, 4, 5, 6, 0, 7, 8, 2, 9, 10, 3, 11, 12]))
In [136]: np.where(arr.T)[1]
Out[136]: array([ 1, 4, 5, 6, 0, 7, 8, 2, 9, 10, 3, 11, 12])
Like said above. If you want a solution in the form of vectors then numpy is the best choice.
import numpy as np
arr = arr.transpose()
y = np.arange(arr.shape[0])
result = list(map(lambda j: y[j==1], x))
result = np.concatenate(result)
The trick is to use a separate array y for filtering index based on the condition.
You can do this considering matrix as your input:
result = [i for i,x in enumerate(matrix.transpose().flatten()) if x == 1]
You should try with the numpy library in python
Its very effective and easy to use.
v = [[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[1, 0, 0, 0],
[1, 0, 0, 0],
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[0, 0, 0, 1]];
import numpy as np
flattenedArray = np.array(v).ravel()
print flattenedArray
for i in range(len(flattenedArray)):
if flattenedArray[i]>0:
print i
I have a very large numpy.array of integers, where each integer is in the range [0, 31].
I would like to count, for every pair of integers (a, b) in the range [0, 31] (e.g. [0, 1], [7, 9], [18, 0]) how often b occurs right after a.
This would give me a (32, 32) matrix of counts.
I'm looking for an efficient way to do this with numpy. Raw python loops would be too slow.
Here's one way...
To make the example easier to read, I'll use a maximum value of 9 instead of 31:
In [178]: maxval = 9
Make a random input for the example:
In [179]: np.random.seed(123)
In [180]: x = np.random.randint(0, maxval+1, size=100)
Create the result, initially all 0:
In [181]: counts = np.zeros((maxval+1, maxval+1), dtype=int)
Now add 1 to each coordinate pair, using numpy.add.at to ensure that duplicates are counted properly:
In [182]: np.add.at(counts, (x[:-1], x[1:]), 1)
In [183]: counts
Out[183]:
array([[2, 1, 1, 0, 1, 0, 1, 1, 1, 1],
[2, 1, 1, 3, 0, 2, 1, 1, 1, 1],
[0, 2, 1, 1, 4, 0, 2, 0, 0, 0],
[1, 1, 1, 3, 3, 3, 0, 0, 1, 2],
[1, 1, 0, 1, 1, 0, 2, 2, 2, 0],
[1, 0, 0, 0, 0, 0, 1, 1, 0, 2],
[0, 4, 2, 3, 1, 0, 2, 1, 0, 1],
[0, 1, 1, 1, 0, 0, 2, 0, 0, 3],
[1, 2, 0, 1, 0, 0, 1, 0, 0, 0],
[2, 0, 2, 2, 0, 0, 2, 2, 0, 0]])
For example, the number of times 6 is followed by 1 is
In [188]: counts[6, 1]
Out[188]: 4
We can verify that with the following expression:
In [189]: ((x[:-1] == 6) & (x[1:] == 1)).sum()
Out[189]: 4
You can use numpy's built-in diff routine together with boolean arrays.
import numpy as np
test_array = np.array([1, 2, 3, 1, 2, 4, 5, 1, 2, 6, 7])
a, b = (1, 2)
sum(np.bitwise_and(test_array[:-1] == a, np.diff(test_array) == b - a))
# 3
If your array is multi-dimensional, you will need to flatten it first or make some small modifications to the code above.
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])