I am using Matlab.
I compare a zero array A with some other arrays (e.g. [1 1 0 0])
I write the following code:
A=[0 0 0 0];
if (A~=[1 1 0 0] & A~=[1 0 1 0] & A~=[1 1 0 1])
x=1;
else
x=0;
end
I expected to see that x=1 but the answer i get is x=0
what do i wrong ?
~= and & are element wise operators, so the expression
A~=[1 1 0 0] & A~=[1 0 1 0] & A~=[1 1 0 1]
where A = [0 0 0 0] produces the vector output:
[1 0 0 0]
An if statement evaluated on a vector does an implicit all, which in that case evaluates to false.
It's not exactly clear what you want, but if you want to make sure the vector A is not equal to any of [1 1 0 0], [1 0 1 0] or [1 1 0 1] then you need to do this:
x = ~isequal(A, [1 1 0 0]) && ~isequal(A, [1 0 1 0]) && ~isequal(A, [1 1 0 1])
The matlab equality operators compares array element-wise and returns true/false (logical 1/0) for each element. So when you have A = [1 1 0 0], B = [1 0 1 0] and you check for A == B, you don't get 'false' but instead you get [1 0 0 1].
If you want to check if the whole vectors A and B are equal you need to check if the condition
all(A==B)is true or not
I think you are looking to find exact match, so for that you may use this -
%%// If *ANY* of the element-wise comparisons are not-true, give me 1,
%%// otherwise give me 0. Thus, in other words, I am looking to find the
%%// exact match (element-wise) only, otherwise give me 1 as x.
if any(A~=[1 1 0 0] & A~=[1 0 1 0] & A~=[1 1 0 1])
x=1;
else
x=0;
end
Another way to put it would be -
%%// *ALL* elementwise comparisons must be satisfied, to give x as 0,
%%// otherwise give x as 1.
if all(A==[1 1 0 0] & A==[1 0 1 0] & A==[1 1 0 1])
x=0;
else
x=1;
end
Get more info about any and all, that are used here.
Related
I have the following dummy array:
>>> arr
[[0 0 1 0 0 1 0 1 1 1 0 0]
[1 1 0 1 1 0 0 0 0 0 1 1]
[1 1 0 1 0 1 0 0 0 0 1 0]
[1 1 0 1 1 0 1 1 0 0 0 1]
[0 1 0 1 0 1 1 1 0 0 0 1]
[1 0 1 1 1 0 0 1 0 0 1 1]]
I also have some "mutations" I would like to incorporate into my array, at the following positions (note these are generated randomly each time, so I cannot just set them manually):
row = [0 4 3]
col = [11 10 7]
I know I can target each (row, col) pair using fancy indexing with arr[row, col] = -3 (for example, set those elements to -3).
However, what I want to do is a bitwise NOT - aka something like this:
arr[row, col] = ~arr
I tried using np.where(), but it won't accept arr[row, col] b/c it doesn't generate a boolean array.
Any suggestions? How can I create a boolean array to use as a where conditional
(also yes, I know I can make an array of all zeros in the same shape as arr and then set those positions to 1's and use that as a mask - I'd love something cleaner tho)
Thanks!
I'm trying to create a program that uses the Hannan-Rissanen algorithm to compute the sample parameters for an ARMA(p, q) auto-regressive moving average stochastic process.
The main step I'm having difficulty with is calculating the autocovariance function of the time series.
The program should take in an n×1-dimensional column vector Y and compute a k×1-dimensional column vector γ^hat given by:
acvf equation image
where Ybar is the average of the elements of Y.
How can I compute the above sum efficiently? (obviously for loops would work, but I'm trying to get better at vectorized numpy operations) Since I'm using this as a learning experience, I would prefer not to use any numpy functions other than very basic ones like np.sum or np.mean.
The following previous similar question has been asked, but doesn't quite answer my question:
Computing autocorrelation of vectors with numpy (uses np.correlate)
(a few others suffer the same problem of using more advanced numpy functions, or aren't spitting out vectors as I wish to do here.)
Here is one way to replace np.correlate (which I assume is the main difficulty; I'm also assuming you have no desire to hand code an fft):
def autocorr_direct(a, debug=False):
n, _ = a.shape
out = np.zeros((n+1, 2*n-1), a.dtype)
out.reshape(-1)[:2*n*n].reshape(n, 2*n)[::-1, :n] = a*a.T
if debug:
print(out.reshape(-1)[:2*n*n].reshape(n, 2*n))
print(out)
return out.sum(0)
For example:
>>> a = np.array([[1, 1, 2, -1]]).T
>>> autocorr_direct(a, True)
[[-1 -1 -2 1 0 0 0 0]
[ 2 2 4 -2 0 0 0 0]
[ 1 1 2 -1 0 0 0 0]
[ 1 1 2 -1 0 0 0 0]]
[[-1 -1 -2 1 0 0 0]
[ 0 2 2 4 -2 0 0]
[ 0 0 1 1 2 -1 0]
[ 0 0 0 1 1 2 -1]
[ 0 0 0 0 0 0 0]]
array([-1, 1, 1, 7, 1, 1, -1])
>>> np.correlate(a[:, 0], a[:, 0], 'full')
array([-1, 1, 1, 7, 1, 1, -1])
Note the reshape trick that shears the square array a[::-1]*a.T.
Note 2; to get a column vector from a 1D vector X use X[:, None].
I have an array A of 1s and 0s and want to see if the larger array of bits B contains those bits in that exact order?
Example: A= [0 1 1 0 0 0 0 1]
B= [0 1 0 0 1 1 0 0 0 0 1 0 1 0 1]
would be true as A is contained in B
Most solutions I have found only determine if a value IS contained in another matrix, this is no good here as it is already certain that both matrices will be 1s and 0s
Thanks
One (albeit unusual) option, since you're dealing with integer values, is to convert A and B to character arrays and use the contains function:
isWithin = contains(char(B), char(A));
There are some obtuse vectorized ways to to do this, but by far the easiest, and likely just as efficient, is to use a loop with a sliding window,
A = [0 1 1 0 0 0 0 1];
B = [0 1 0 0 1 1 0 0 0 0 1 0 1 0 1];
vec = 0:(numel(A)-1);
for idx = 1:(numel(B)-numel(A)-1)
if all(A==B(idx+vec))
fprintf('A is contained in B\n');
break; % exit the loop as soon as 1 match is found
end
end
Or if you want to know the location(s) in B (of potentially multiple matches) then,
A = [0 1 1 0 0 0 0 1];
B = [0 1 0 0 1 1 0 0 0 0 1 0 1 0 1];
C = false(1,numel(B)-numel(A)-1);
vec = 0:(numel(A)-1);
for idx = 1:numel(C)
C(idx) = all(A==B(idx+vec));
end
if any(C)
fprintf('A is contained in B\n');
end
In this case
>> C
C =
1×6 logical array
0 0 0 1 0 0
You can use the cross-correlation between two signals for this, as a measure of local similarity.
For achieving good results, you need to shift A and B so that you don't have the value 0 any more. Then compute the correlation between the two of them with conv (keeping in mind that the convolution is the cross-correlation with one signal flipped), and normalize with the energy of A so that you get a perfect match whenever you get the value 1:
conv(B-0.5, flip(A)-0.5, 'valid')/sum((A-0.5).^2)
In the normalization term, flipping is removed as it does not change the value.
It gives:
[0 -0.5 0.25 1 0 0 -0.25 0]
4th element is 1, so starting from index equal to 4 you get a perfect match.
I have a 3D array of dimensions (200,200,3). These are images of dimensions (200,200) stacked using numpy.dstack. I would like to count the number of values along axis=2 that are greater than a corresponding 2D threshold array of dimensions (200,200). The output counts array should have dimensions (200,200). Here is my code so far.
import numpy as np
stacked_images=np.random.rand(200,200,3)
threshold=np.random.rand(200,200)
counts=(stacked_images<threshold).sum(axis=2)
I am getting the following error.
ValueError: operands could not be broadcast together with shapes (200,200,3) (200,200)
The code works if threshold is an integer/float value. For example.
threshold=0.3
counts=(stacked_images<threshold).sum(axis=2)
Is there a simple way to do this if threshold is a 2D array? I guess I am not understanding numpy broadcasting rules correctly.
numpy is expecting to make a value by value operation. In your case you seem to be wanting to know if any value in the full Z (axis=2) trace exceeds the equivalent x, y value in threshold.
As so just make sure threshold has the same shape, namely by building a 3D threshold using whatever method you prefer. Since you mentioned numpy.dstack:
import numpy as np
stacked_images = np.random.rand(10, 10, 3)
t = np.random.rand(10, 10)
threshold = np.dstack([t, t, t])
counts = (stacked_images < threshold).sum(axis=2)
print(counts)
, which results in:
[[2 0 3 3 1 3 1 0 1 2]
[0 1 2 0 0 1 0 0 1 3]
[2 1 3 0 3 2 1 3 1 3]
[2 0 0 3 3 2 0 2 0 1]
[1 3 0 0 0 3 0 2 1 2]
[1 1 3 2 3 0 0 3 0 3]
[3 1 0 1 2 0 3 0 0 0]
[3 1 2 1 3 0 3 2 0 2]
[3 1 1 2 0 0 1 0 1 0]
[0 2 2 0 3 0 0 2 3 1]]
I have an array of binary data with long stretches of ones and zeros and I want to find the indices of when it changes.
a = [ 1 1 1 1 1 0 0 0 0 0 0 1 1]
I want to search for [1 0] and [0 1] to find the transition points. I'd like to avoid long loops to find these if possible. Any ideas?
Something like this should do the job:
b = diff(a); % (assuming 'a' is a vector)
oneFromZero = find(b == 1) + 1; % vector of indices of a '1' preceded by a '0'
zeroFromOne = find(b == -1) + 1; % vector of indices of a '0' preceded by a '1'
Depending on what you want exactly, you may or may not want to add 1 to the resulting arrays of indices.
I'd go with
d = a(1:end-1) - a(2:end);
ind = find(d);
Here, d will be 1 where you have a ... 1 0 ... in your bit string and it will be -1 where you have a ... 0 1 .... All the other elements in d will be 0, since, at those positions, the bits are equal to their neighbour.
With this in place, you can use find to get the indices where these two patterns occur. The whole procedure is of O(n) complexity, where n=length(a), since it requires two passes through a.
For a = [ 1 1 1 1 1 0 0 0 0 0 0 1 1] the above code computes ind = [5 11].
To search for an arbitrary pattern of zeros and ones:
You can compute a convolution (conv) of the two sequences in bipolar (±1) form and then find the maxima. Since the convolution flips one of the inputs, it has to be flipped to undo that:
a = [ 1 1 1 1 1 0 0 0 0 0 0 1 1];
pattern = [0 1 1];
result = find(conv(2*a-1, 2*pattern(end:-1:1)-1, 'valid')==numel(pattern));
In this example
result =
11
which means that [0 1 1] appears in a only once, namely at index 11.
A simpler approach is to use strfind, exploiting the undocumented fact that this function can be applied to numeric vectors:
result = strfind(a, pattern);