I am expanding the arrayfun code of the thread To Find Double Sequence With Transforms in Matlab? for a list of vectors in cellfun (DD).
Pseudocode
DD = {[9 1 5 6 6 6 5 1 1 0 7 7 7 7 7 8], [1 1 1 4], [7 7 7]};
d = cellfun(#(i) diff(diff([0 i 0]) == 0), DD, 'Uniform', false);
y = cellfun(#(z) ...
arrayfun(#(i,j) DD{i}(i:j), find(z>0), find(z<0), 'Uniform', false), ...
d, 'Uniform', false););
Expected output
y = { {[6 6 6], [1 1], [7 7 7]}, ...
{[1 1 1]}, ...
{[7 7 7]} };
Error
Index exceeds matrix dimensions.
Error in findDoubleSequenceAnonFunction>#(i,j)DD{i}(i:j)
Error in
findDoubleSequenceAnonFunction>#(z)arrayfun(#(i,j)DD{i}(i:j),find(z>0),find(z<0),'Uniform',false)
Error in findDoubleSequenceAnonFunction (line 5)
y = cellfun(#(z) ...
Comments
d = cellfun(.... I am applying the function diff(diff(... in cellfun. It should be ok.
y = cellfun(.... Need to have cellfun here because have the again a cell of vectors in d. Somehow, the cellfun-arrayfun is complicating.
How can you have cellfun-arrayfun combination here?
Just use a for-loop, easier to read:
XX = {[9 1 5 6 6 6 5 1 1 0 7 7 7 7 7 8], [1 1 1 4], [7 7 7]};
YY = cell(size(XX));
for i=1:numel(XX)
x = XX{i};
d = diff(diff([0 x 0]) == 0);
YY{i} = arrayfun(#(i,j) x(i:j), find(d>0), find(d<0), 'Uniform',false);
end
Result:
>> celldisp(YY)
YY{1}{1} =
6 6 6
YY{1}{2} =
1 1
YY{1}{3} =
7 7 7 7 7
YY{2}{1} =
1 1 1
YY{3}{1} =
7 7 7
Related
I want to split an array into several arrays automatically. For example:
a=[1 2 3 4 5 6 7 8 9]
b=[2 5]
Thus, I want to split it to:
c1=[1 2]
c2=[3 4 5]
c3=[6 7 8 9]
How to do it?
A simple way is to use mat2cell:
a = [1 2 3 4 5 6 7 8 9];
b = [2 5];
c = mat2cell(a, 1, diff([0 b numel(a)]));
This gives a cell array c containing the subarrays of a:
>> celldisp(c)
c{1} =
1 2
c{2} =
3 4 5
c{3} =
6 7 8 9
Question 1: I have a 1x15 array, comprising of positive integers and negative integers. I wish to implement a MATLAB code which keeps all positive integers and skips the cells with negative contents.
I have tried the following:
X = [1 2 3 4 5 -10 1 -5 4 6 8 9 2 4 -2];
[r c] = size(X);
for i=1:r
for j=1:c
if X(i,j)<0
X(i,j)=X(i,j+1)
end
end
end
The output should be:
X_new = [1 2 3 4 5 1 4 6 8 9 2 4]
How do I do this?
Question 2:
X = [1 2 3 4 5 -10 1 -5 4 6 8 9 2 4 -2]
Y = [5 3 8 9 4 5 6 7 4 7 9 5 2 1 4]
From Question 1,
X_new = [1 2 3 4 5 1 4 6 8 9 2 4]
I need to delete the corresponding values in Y so that:
Y_new = [5 3 8 9 4 6 4 7 9 5 2 1]
How do I perform this?
In MATLAB, manipulating arrays and matrices can be done much easier than for-loop solutions,
in your task, can do find and delete negative value in the array, simply, as follows:
Idx_neg = X < 0; % finding X indices corresponding to negative elements
X ( Idx_neg ) = []; % removing elements using [] operator
Y ( Idx_neg ) = []; % removing corresponding elements in Y array
I have a vector and I would like to extract all the 4's from it:
x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4]
so that I will get 4 vectors or a cell containing the 4 blocks of 4's:
[4 4], [4], [4 4 4], [4 4 4 4]
Thanks!
You can create cells from the appropriate ranges using arrayfun:
x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4];
x = [0, x, 0]; D = diff (x==4); % pad array and diff its mask
A = find (D == 1); B = find (D == -1); % find inflection points
out = arrayfun (# (a,b) {x(a+1 : b)}, A, B) % collect ranges in cells
This should be pretty fast, using accumarray:
X = 4;
%// data
x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4]
%// mask all 4
mask = x(:) == X
%// get subs for accumarray
subs = cumsum( diff( [0; mask] ) > 0 )
%// filter data and sort into cell array
out = accumarray( subs(mask), x(mask), [], #(y) {y} )
idx=find(x==4);
for (i= 1:length(idx))
if (i==1 || idx(i-1)!=idx(i)-1)if(i!=1) printf(",") endif; printf("[") endif;
printf("4");
if (i<length(idx)&&idx(i+1)==idx(i)+1) printf(",") else printf("]") endif
endfor
Note this won't give the actual vectors, but it will give the output you wanted. The above is OCtave code. I am pretty sure changing endfor and endif to end would work in MAtlab, but without testing in matlab, I am not positive.[edited in light of comment]
with regionprops we can set property PixelValues so the function returns 1s instead of 4s
x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4]
{regionprops(x==4,'PixelValues').PixelValues}
if we set property PixelIdxList the function returns a cell of indices of 4s:
{regionprops(x==4,'PixelIdxList').PixelIdxList}
Update(without image processing toolbox):
this way we can get number of elements of each connected components:
c = cumsum(x~=4)
h=hist(,c(1):c(end));
h(1)=h(1)+~c(1);
result = h(h~=1)-1
I want to Create a matrix like
A = [1 2 3 ;4 5 6; 7 8 9];
I want to do it like this,
A = 1 + val : 1 : 3 + val ;
val = [0 3 6];
But I am only getting [1 2 3] , Not 2D matrix .
Try this,
val = [0 3 6];
A = bsxfun(#plus,val',1:3);
A =
1 2 3
4 5 6
7 8 9
My problem is about storing some changeble number of value groups as one dimensional in an array, a vector or a matrix in matlab.
If we think the values are like this:
1 1 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 3 3 4 4 4 4 4 4 4 5 5 5 6 6 6 6 6....
I want to keep them dynamically in a structure as each group is one element of this structure, for example:
a = [1 1 1 1 1 1 1 1]
b = [2 2 2 2 2]
c = [3 3 3 3 3 3 3]
d = [4 4 4 4 4 4 4]
e = [5 5 5]
f = [6 6 6 6 6]
x = [a,b,c,d,e,f]
How can I do this?
Use a structure:
>> myStruct.a = [1 1 1 1 1 1 1 1];
>> myStruct.b = [2 2 2 2 2];
>> myStruct.c = [3 3 3 3 3 3 3];
>> myStruct.d = [4 4 4 4 4 4 4];
>> myStruct.e = [5 5 5];
>> myStruct.f = [6 6 6 6 6]
myStruct =
a: [1 1 1 1 1 1 1 1]
b: [2 2 2 2 2]
c: [3 3 3 3 3 3 3]
d: [4 4 4 4 4 4 4]
e: [5 5 5]
f: [6 6 6 6 6]
Or, if you want to numerically index your object, use a cell array:
>> myCell{1} = [1 1 1 1 1 1 1 1];
>> myCell{2} = [2 2 2 2 2];
>> myCell{3} = [3 3 3 3 3 3 3];
>> myCell{4} = [4 4 4 4 4 4 4];
>> myCell{5} = [5 5 5];
>> myCell{6} = [6 6 6 6 6];
>> myCell{:}
ans =
1 1 1 1 1 1 1 1
ans =
2 2 2 2 2
ans =
3 3 3 3 3 3 3
ans =
4 4 4 4 4 4 4
ans =
5 5 5
ans =
6 6 6 6 6