For example:
a=[1 1 0 0 1 1 0 1 1 1 0 0];
Now i want to sum only the ones which are divides by the zeros:
ones=[2 2 3] - That means two ones,then we have 2 zeros which we do not count,then again two ones etc.
How can i do this?
Well, I would suggest finding all places where it switches from 0 to 1 and then finding all places where it switches from 1 to 0, and using those indices to find those lengths. The problem arises at the edges where if the first entry is 1, it doesn't switch to one from zero, and if the last entry is 1, we never find it because nothing switches to 0 at the end. In order to avoid this problem easily, we can add a 0 in the beginning and one at the end. This way we're guaranteed to find each one of those bursts of ones. In essence:
b = [0 a 0];
d = diff(b);
posEdge = find(d==1);
negEdge = find(d==-1);
countOnes = negEdge - posEdge
Related
I have the following three vectors:
trans_now=[1 2 4]; data2send=[1 0 0 1]; datasent=[0 0 0 0];
I want to set datasent to 1 for those nodes that are members of tran_now and whose data2send status is 1. e.g 4 is a member of trans_now and data2send(4) is 1 therefore datasent(4) should be set to 1.
I can do it using for loop and if statement as shown in the code below.
for i=1:length(trans_now)
if data2send(trans_now(i))==1
datasent(trans_now(i))=1;
end
end
However I want one liner code for this. The one liner code that I tried is
req_sent(req2send(trans_now)==1)=1;
But it doesn't work.
The output should set datasent vector to [1 0 0 1].
you could solve this in 2 ways:
1.
data_sent(trans_now) = data2send(trans_now)
the output is:
data_sent =
1 0 0 1
In this solution I assumed that all the initial values of data_sent are starting as 0 and that you need to assign it once.
2.
datasent(intersect(find(data2send == 1), trans_now)) = 1
output is:
data_sent =
1 0 0 1
In this solution no assumption is used and you assign only indices where data2send == 1 and also appear in trans_now
I have searched the forum and have not found enough info to help me solve this problem.
Consider the set (cell of vectors)
A = {[1],[1 2],[2],[1 2 3],[1 2 3 4],[1 3]}
I want to construct a matrix B that looks like
B = [1 1 0 1 1 1
0 1 0 1 1 0
0 1 1 1 1 0
0 0 0 1 1 0
0 0 0 0 1 0
0 0 0 1 1 1]
The matrix B specifies membership of vectors with respect to each other. That is, the first row looks at the first element in A, [1], and checks if it is a member of the other vectors, placing a 1 if it is a member and a 0 otherwise.
I can do this using two for loops: one over the elements of A, and another nested, for each element of A, that checks membership with respect to every other member of A.
I want to avoid using for loops. Is there a vectorized solution for obtaining B from A?
With cell arrays it's hard to avoid loops, or their cousin cellfun. This is how I would do it:
[ii, jj] = ndgrid(1:numel(A)); % indices of all possible pairs
result = cellfun(#(x,y) all(ismember(x,y)), A(ii), A(jj)); % see if all elements in the
% first are present in the second
Well you asked for it, so here's an almost* vectorized solution using bsxfun and permute -
lens = cellfun('length',A)
vals = [A{:}]
mask = bsxfun(#ge,lens,[1:max(vals)]')
a = nan(size(mask))
a(mask) = vals
matches = bsxfun(#eq,a,permute(a,[3,4,1,2]));
out = bsxfun(#eq,squeeze(sum(any(matches,3),1)),lens(:))
*: Almost because of the use of cellfun at the start with cellfun('length',A), but since its just getting the length of the cells there, so computationally would be negligible .
Also, please note that this approach would use a lot of memory resources, so might not be beneficial, but just respecting the requirements of a vectorized solution as much as possible!
l2 = [{'walk', 'water', 'warm', 'cheer', 'word', 'happy', 'whim', 'womb', 'wear', 'well'};
{'hello', 'here', 'hat', 'that', 'happy', 'hide', 'awesome', 'there', 'howl', 'harry'};
{'look', 'listen', 'lyer', 'hateful', 'lost', 'hatred', 'plot', 'player', 'plow', 'lay'};
{'goat', 'meat', 'hope', 'house', 'love', 'wall', 'down', 'up', 'sky', 'mount'};
{'go', 'golf', 'loser', 'gyrus', 'terrible', 'gallore', 'tug', 'thor', 'gear', 'leg'}];
So I have this data above, and I want to be able to separate each row in terms of it being either positive or negative.
As you can see above: My first row has 2 positive targets amongst neutral words and the third row has 2 negative targets amongst neutral words.
Now if I was running this where the participant saw each word in a sequence per row, how can I get an accuracy for their response to a row with positive targets vs negative target?
Any ideas?
Please help, I just cant figure it out
So far I was thinking of using logical indexing to separate positive targets and negative target, but how do I do that with cell rows?
I have this:
positive_t = [1 1; 1 1; 0 0; 1 1; 0 0]
This above denotes all the positive targets as 1 and negative targets as 0 but how would I be able to separate them properly row by row? Also. Then if I want to find how many time the participants got the answer for positive row vs negative row. How can I save the accuracy of that?
I assume 1) you want to test a person's ability to pick out positive or negative words and 2) you already have a standard answer ( as your test standard ) that you're going to compare testee's answer against.
I don't know what your definition of positive is, so I'm also being tested by you in a sense, but let's assume that you have this standard answer :
std_answer = logical([ 0 0 0 0 0 1 0 0 0 1;... % 'happy' and 'well'
0 0 0 0 1 0 1 0 0 0;... % 'happy' and 'awesome'
0 0 0 1 0 1 0 0 0 0;... % 'hateful' and 'hatred'
0 0 1 0 1 0 0 0 0 0;... % 'hope' and 'love'
0 0 1 0 1 0 0 0 0 0 ]); % 'loser' and 'terrible'
The std_answer here is an logical array that has the same number of elements as your l2. It has value of 1 wherever your answer is ( which of course, as a tester you already know. Here I'm just taking some guess and assume the standard answer to make an example) and 0 otherwise.
You can apply this mask to your l2 and the result will be your answers
answers = l2(std_answer);
If you really wish to do it row by row, of course you can do this:
for ii = 1:size(l2, 1)
sublist = l2(ii, :);
submask = std_answer(ii, :);
answer = sublist(submask);
end
At the end of the test, you'll have a testee response ( let's say you named it test_response) that's also a 5*10 logical array. You can compare the testee response to standard answer by using logical operation:
score = test_response & std_answer ;
score will also be a logical array whose 1 indicate a match between testee response and standard answer.
Given a vector of zeros and ones in MATLAB, where the zeros represent an event in time, I would like to add additional ones before and after the existing ones in order to capture additional variation.
Example: I would like to turn [0;0;1;0;0] into [0;1*;1;1*;0] where 1* are newly added ones.
Assuming A to be the input column vector -
%// Find all neighbouring indices with a window of [-1 1]
%// around the positions/indices of the existing ones
neigh_idx = bsxfun(#plus,find(A),[-1 1])
%// Select the valid indices and set them in A to be ones as well
A(neigh_idx(neigh_idx>=1 & neigh_idx<=numel(A))) = 1
Or use imdilate from Image Processing Toolbox with a vector kernel of ones of length 3 -
A = imdilate(A,[1;1;1])
You can do it convolving with [1 1 1], and setting to 1 all values greater than 0. This works for column or row vactors.
x = [0;0;1;0;0];
y = double(conv(x, [1 1 1],'same')>0)
Purely by logical indexing:
>> A = [0 1 1 0 0];
>> A([A(2:end) 0] == 1 | [0 A(1:end-1)] == 1) = 1;
>> disp(A);
A =
1 1 1 1 0
This probably merits an explanation. The fact that it's a 3 element local neighbourhood makes this easy. Essentially, take two portions of the input array:
Portion #1: A starting from the second element to the last element
Portion #2: A starting from the first element to the second-last element
We place the first portion into a new array and add 0 at the end of this array, and check to see which locations are equal to 1 in this new array. This essentially shifts the array A over to the left by 1. Whichever locations in this first portion are equal to 1, we set the corresponding locations in A to be 1. The same thing for the second portion where we are effectively shifting the array A over to the right by 1. To shift to the right by 1, we prepend a 0 at the beginning, then extract out the second portion of the array. Whichever locations in this second portion are equal to 1 are also set to 1.
At the end of this operation, you would essentially shift A to the left by 1 and save this as a separate array. Also, you would shift to the right by 1 and save this as another array. With these two, you simply overlap on top of the original to obtain the final result.
The benefit of this method over its predecessors in this post is that this doesn't require computations of any kind (bsxfun, conv, imdilate etc.) and purely relies on indexing into arrays and using logical operators1. This also handles boundary conditions and can work on either row or column vectors.
Some more examples with boundary cases
>> A = [0 0 1 1 0];
>> A([A(2:end) 0] == 1 | [0 A(1:end-1)] == 1) = 1
A =
0 1 1 1 1
>> A = [0 0 0 0 1];
>> A([A(2:end) 0] == 1 | [0 A(1:end-1)] == 1) = 1
A =
0 0 0 1 1
>> A = [1 0 1 0 1];
>> A([A(2:end) 0] == 1 | [0 A(1:end-1)] == 1) = 1
A =
1 1 1 1 1
1: This post is dedicated to Troy Haskin, one who believes that almost any question (including this one) can be answered by logical indexing.
The title might be confusing, here's a particular example to explain myself. Also, I'm not sure how do you call the diagonal that starts in (1,2) and goes onward: (2,3) ; (3,4) and so on. Non-principal, non-main diagonal, not sure at all.
3x3 case
-1 1 0
-1 0 1
0 -1 1
4x4 case
-1 1 0 0
-1 0 1 0
-1 0 0 1
0 -1 1 0
0 -1 0 1
0 0 -1 1
So if the original matrix was a 4x4 (or any other size), I am able to make a matrix the size of the second example. I now have to insert the -1 and 1's in this fashion. This means n-1 number of -1's inserted if j=1, and then, a n-1 number of ones in the non-principal diagonal. When this is done, it's the same but for j=2 and the next non-principal diagonal, and so on.
Thing is, I'm thinking all the time about loops, and too many cases arise, because what I want is to be able to do this for any possible dimension, not for a particular case.
But then I saw this post Obtaining opposite diagonal of a matrix in Matlab
With this answer: A(s:s-1:end-1)
And it seems like a much cleaner way of doing it, since my own way (not finished since I'm not able to figure all the cases) has too many conditions. With a sentence like that, I could choose the diagonal, insert ones, and do it as many times as required, depending of the n dimension.
This leaves the problem of inserting the -1's, but I guess I could manage something.
It seems to mee that you want to obtain the following matrix B of size n × (n-1)*n/2
n = 4;
idx = fliplr(fullfact([n n]));
idx(diff(idx')<=0,:) = [];
m = size(idx,1);
B = zeros(m,n);
B(sub2ind(size(B),1:m,idx(:,1)')) = -1;
B(sub2ind(size(B),1:m,idx(:,2)')) = 1;
Approach #1
Here's a vectorized approach that has more memory requirements than a non-vectorized or for-loop based one. So, it could be tried out for small to medium sized datasizes.
The basic idea is this. For n=4 as an example, we take
-1 1 0 0
-1 0 1 0
-1 0 0 1
as the basic building block, replicate it n-1 i.e. 3 times and then remove the rows that aren't supposed to be part of the final output as per the requirements of the problem. Because of this very nature, this solution has more memory requirements, as we need to remove rows 6,8,9 for n = 4 case. But this gives us the opportunity to work with everything in one go.
N = n-1; %// minus 1 of the datasize, n
blksz = N*(N+1); %// number of elements in a (n-1)*n blocksize that is replicated
b1 = [-1*ones(N,1) eye(N)] %// Create that special starting (n-1)*n block
idx1 = find(b1~=0) %// find non zero elements for the starting block
idx2 = bsxfun(#plus,idx1,[0:N-1]*(blksz+N)) %// non zero elements for all blocks
b1nzr = repmat(b1(b1~=0),[1 N]) %// elements for all blocks
vald_ind = bsxfun(#le,idx2,[1:N]*blksz) %// positions of valid elements all blocks
mat1 = zeros(N,blksz) %// create an array for all blocks
mat1(idx2(vald_ind)) = b1nzr(vald_ind) %// put right elements into right places
%// reshape into a 3D array, join/concatenate along dim3
out = reshape(permute(reshape(mat1,N,N+1,[]),[1 3 2]),N*N,[])
%// remove rows that are not entertained according to the requirements of problem
out = out(any(out==1,2),:)
Approach #2
Here's a loop based code that could be easier to get a hold on if you have to explain it to yourself or just people and most importantly scales up pretty well on performance criteria across varying datasizes.
start_block = [-1*ones(n-1,1) eye(n-1)] %// Create that special starting (n-1)*n block
%// Find starting and ending row indices for each shifted block to be repeated
ends = cumsum([n-1:-1:1])
starts = [1 ends(1:end-1)+1]
out = zeros(sum(1:n-1),n) %// setup all zeros array to store output
for k1 = 1:n-1
%// Put elements from shifted portion of start_block for creating the output
out(starts(k1):ends(k1),k1:end) = start_block(1:n-k1,1:n-k1+1)
end
With n=4, the output -
out =
-1 1 0 0
-1 0 1 0
-1 0 0 1
0 -1 1 0
0 -1 0 1
0 0 -1 1
I don't know if I understood properly, but is this what you are looking for:
M=rand(5);
k=1; % this is to select the k-th diagonal
D=diag(ones(1,size(M,2)-abs(k)), k);
M(D==1)=-1;
M =
0.9834 -1.0000 0.8402 0.6310 0.0128
0.8963 0.1271 -1.0000 0.3164 0.6054
0.8657 0.6546 0.3788 -1.0000 0.5765
0.8010 0.8640 0.2682 0.4987 -1.0000
0.5550 0.2746 0.1529 0.7386 0.6550