randperm of multiple columns - matlab

on a previous question here Sampling the answer given for sample on the last line of code only returns 1000x1 rather than 1000x6?
%%
normIdx = strmatch('normal.', Book2);
normalSubset = fulldata(normIdx, :);
normal = randperm(size(normalSubset , 1));
p = normal(1:750)-1;
%
smurfIdx = strmatch('smurf.', Book2);
smurfSubset = fulldata(smurfIdx, :);
smurf = randperm(size(smurfSubset , 1));
a = smurf(1:250)-1;
%
normalSample = normalSubset (p, :);
smurfSample = smurfSubset (a, :);
%
sample = [normalSample ; smurfSubset]
%
sample = sample(randperm(1000)); % this line
I tried:
sample = randperm( size(sample, 1));
This outputs 28 thousand records on one line, obviously not what I want. I then tried:
rows = 1000;
columns = 6;
%# pick random columns
indY = randperm( size(sample,2) );
indY = indY(1:columns);
%# pick random rows
indX = randperm( size(sample,1) );
indX = indX(1:rows)';
%# filter data
sample = [indX ; indY];
But I couldnt concatenate the last line? This was only an attempt to try fix the 1000x6 problem, if anyone could come up with a better way "a working way".

how about
sample = sample(randperm(1000),:);

Related

Using xlswrite to save numerical data

Hi I would like to save numerical data from an operation inside a loop. Lets see my segmentation example:
clear all, clc;
a=1:35;
A = arrayfun( #(x) sprintf( '%04d', x ), a, 'UniformOutput', false );
I = cellfun( #(b) imread( ['C:Teste/' b '/c1/' b '.png'] ), A, 'UniformOutput', false );
for i = a
% Gaussian Filter
W = fspecial('gaussian',[10,10],2);
J = imfilter(I,W);
% Finding Circular objects -- Houng Transform
[centers, radii, metric] = imfindcircles(J,[5 10], 'Sensitivity',0.93,'Edge',0.27);
idx_mask = ones(size(radii));
min_dist = 2; % relative value.
for i = 2:length(radii)
cur_cent = centers(i, :);
for j = 1:i-1
other_cent = centers(j,:);
x_dist = other_cent(1) - cur_cent(1);
y_dist = other_cent(2) - cur_cent(2);
if sqrt(x_dist^2+y_dist^2) < min_dist*(radii(i) + radii(j)) && idx_mask(j) == 1
idx_mask(i) = 0;
break
end
end
end
idx_mask = logical(idx_mask);
centers_use = centers(idx_mask, :);
radii_use = radii(idx_mask, :);
metric_use = metric(idx_mask, :);
viscircles(centers_use, radii_use,'EdgeColor','b');
a=length(centers_use)
end
So the point is to save the 35 results in one column of an xls file.
I was trying to do this but only the last element of the loop is printed in the exel file...
filename = 'testdata.xlsx';
A = vertcat('Test', 'Results', num2cell(a'));
sheet = 1;
xlRange = 'F03';
xlswrite(filename,A,sheet,xlRange)
Can please anyone help me out? I know there many questions related to this one but none of them covers my issue...
I will leave here one image for testing:
Thanks a lot in advance.
John
As #excaza said, you need to expand b
a=1:35;
for i = a
b=10+a;
end
filename = 'testdata.xlsx';
A = vertcat('Example', 'Results', num2cell(b'));
sheet = 1;
xlRange = 'B1';
xlswrite(filename,A,sheet,xlRange)

Finding the coordinates of a sub-image in an image in Matlab

I need to find the coordinates of a 3D sub-image location residing in a 3D image in Matlab. Can anyone help me?
Thanks,
The following code essentially scans through the large array A and compare each element against the first one in the small array B. If an equal is found, a part of A, of which the size is same as of B, is picked out and compared against B.
clear;clc
% reproduce your scenario
A = randi(100, [30, 20, 10]);
B = A(20:30, 1:18, 4:end);
% counter-case verification
% B(end)=200;
% speed up
lenA = numel(A);
[sa1,sa2,sa3] = size(A);
[sb1,sb2,sb3] = size(B);
% a cumbersome method
eqflag = 0;
counterA = 1;
while (counterA <= lenA)
if A(counterA) == B(1)
[subA1,subA2,subA3] = ind2sub([sa1,sa2,sa3],counterA);
if ( (subA1+sb1-1)<=sa1 ) && ( (subA2+sb2-1)<=sa2 ) ...
&& ( (subA3+sb3-1)<=sa3 ) && isequal( B, ...
A(subA1+(1:sb1)-1,subA2+(1:sb2)-1,subA3+(1:sb3)-1) )
eqflag = 1;
break;
end
end
counterA = counterA + 1;
end
if eqflag
fprintf('found matching starting at A(%d, %d, %d).\n', ...
subA1, subA2, subA3);
fprintf('matching region A(%d:%d, %d:%d, %d:%d).\n', ...
subA1, subA1+sb1-1, subA2, subA2+sb2-1, subA3, subA3+sb3-1);
else
fprintf('no matching found.\n');
end
clearvars sa* lenA counterA
% --------------
% a parallel way
[sa1,sa2,sa3] = size(A);
match_first = find(A==B(1));
[m1,m2,m3] = ind2sub([sa1,sa2,sa3],match_first);
region_first_ind = intersect( intersect(find(m1+sb1-1<=sa1), ...
find(m2+sb2-1<=sa2)),find(m3+sb3-1<=sa3)); % array size issue
region_first = num2cell( [m1(region_first_ind),m2(region_first_ind),...
m3(region_first_ind)], 2);
region = cellfun(#(v) [v;v+[sb1,sb2,sb3]-1], region_first, ...
'UniformOutput', false);
region_match = cellfun(#(v) isequal(A(v(1):v(2), v(3):v(4), v(5):v(6)),...
B), region, 'UniformOutput', false);
match = cell2mat(region([region_match{:}]));
if ~isempty(match)
fprintf('found matching starting at A(%d, %d, %d).\n', ...
match(1), match(3), match(5));
fprintf('matching region A(%d:%d, %d:%d, %d:%d).\n', ...
match(1), match(2), match(3), match(4), match(5), match(6));
else
fprintf('no matching found.\n');
end

Subtracting each elements of a row vector , size (1 x n) from a matrix of size (m x n)

I have two matrices of big sizes, which are something similar to the following matrices.
m; with size 1000 by 10
n; with size 1 by 10.
I would like to subtract each element of n from all elements of m to get ten different matrices, each has size of 1000 by 10.
I started as follows
clc;clear;
nrow = 10000;
ncol = 10;
t = length(n)
for i = 1:nrow;
for j = 1:ncol;
for t = 1:length(n);
m1(i,j) = m(i,j)-n(1);
m2(i,j) = m(i,j)-n(2);
m3(i,j) = m(i,j)-n(3);
m4(i,j) = m(i,j)-n(4);
m5(i,j) = m(i,j)-n(5);
m6(i,j) = m(i,j)-n(6);
m7(i,j) = m(i,j)-n(7);
m8(i,j) = m(i,j)-n(8);
m9(i,j) = m(i,j)-n(9);
m10(i,j) = m(i,j)-n(10);
end
end
end
can any one help me how can I do it without writing the ten equations inside the loop? Or can suggest me any convenient way especially when the two matrices has many columns.
Why can't you just do this:
m01 = m - n(1);
...
m10 = m - n(10);
What do you need the loop for?
Even better:
N = length(n);
m2 = cell(N, 1);
for k = 1:N
m2{k} = m - n(k);
end
Here we go loopless:
nrow = 10000;
ncol = 10;
%example data
m = ones(nrow,ncol);
n = 1:ncol;
M = repmat(m,1,1,ncol);
N = permute( repmat(n,nrow,1,ncol) , [1 3 2] );
result = bsxfun(#minus, M, N );
%or just
result = M-N;
Elapsed time is 0.018499 seconds.
or as recommended by Luis Mendo:
M = repmat(m,1,1,ncol);
result = bsxfun(#minus, m, permute(n, [1 3 2]) );
Elapsed time is 0.000094 seconds.
please make sure that your input vectors have the same orientation like in my example, otherwise you could get in trouble. You should be able to obtain that by transposements or you have to modify this line:
permute( repmat(n,nrow,1,ncol) , [1 3 2] )
according to your needs.
You mentioned in a comment that you want to count the negative elements in each of the obtained columns:
A = result; %backup results
A(A > 0) = 0; %set non-negative elements to zero
D = sum( logical(A),3 );
which will return the desired 10000x10 matrix with quantities of negative elements. (Please verify it, I may got a little confused with the dimensions ;))
Create the three dimensional result matrix. Store your results, for example, in third dimension.
clc;clear;
nrow = 10000;
ncol = 10;
N = length(n);
resultMatrix = zeros(nrow, ncol, N);
neg = zeros(ncol, N); % amount of negative values
for j = 1:ncol
for i = 1:nrow
for t = 1:N
resultMatrix(i,j,t) = m(i,j) - n(t);
end
end
for t = 1:N
neg(j,t) = length( find(resultMatrix(:,j,t) < 0) );
end
end

Dataset minus 10%

Below is a method of sampling 10% of my data:
%%
% Normal
normIdx = strmatch('normal.', K2);
normalSubset = cluster2(normIdx, :);
normal = randperm(size(normalSubset , 1));
p = (normal(1:3495))';
%% DoS
DoSIdx = strmatch('DoS', K2);
DoSSubset = cluster2(DoSIdx, :);
DoS = randperm(size(DoSSubset , 1));
a = (DoS(1:8))';
%%
ProbeIdx = strmatch('Probe', K2);
ProbeSubset = cluster2(ProbeIdx, :);
Probe = randperm(size(ProbeSubset , 1));
d = (Probe(1:71))';
%%
normalSample = normalSubset (p, :);
%%
DoSSample = DoSSubset (a, :);
%%
ProbeSample = ProbeSubset (d, :);
%%
idx = [normIdx(p);DoSIdx(a);ProbeIdx(d)];
%
sample = [normalSample ; DoSSample ; ProbeSample]
%
shuffle = randperm(3574);
%
TestData = sample(shuffle,:);
%
TestDataLabels = K2(idx (shuffle), :);
I was wondering how I could then remove this 10% from the dataset (cluster2)? Note that when I say 10% I have worked this out, hence (Probe(1:71) which is 10% of the probe class etc
IF i understand it correctly, you have an index vector idx that contains all the rows that you want to preserve.
In this case the solution is quite simple, to remove them you can follow the approach indicated by #H.Munster, but with the correct index:
cluster2(idx, :) = [];

matching row samples to class labels

I have a small problem with the below code the last line to be specific, I am attempting to find the class names of my "sample" by that I mean I need to know which normal and which smurf belongs to each line of my 1000x6 sample.
%% sampling
normIdx = strmatch('normal.', Book2);
normalSubset = fulldata(normIdx, :);
normal = randperm(size(normalSubset , 1));
p = (normal(1:750)-1)';
%
smurfIdx = strmatch('smurf.', Book2);
smurfSubset = fulldata(smurfIdx, :);
smurf = randperm(size(smurfSubset , 1));
a = (smurf(1:250)-1)';
%
normalSample = normalSubset (p, :);
smurfSample = smurfSubset (a, :);
%
sample = [normalSample ; smurfSample]
%
sample = sample(randperm(1000),:);
%
idx = [a ; p];
K1 = Book2(idx (sample==1), :)
K1 should equal 1000 sample class labels of which 750 should be normal and 250 should be smurf and they should correspnd exactly to the same line in the sample. Book2 contains the class labels I also have fulldata from which the sample was derived.
Atm K1 results in:
Index exceeds matrix dimensions
There could just be an easy way of matching the data of the sample to the data in fulldata but im not sure if there could be repeating data in fulldata... so matching is out and because sample is random so I am thrown off as to what I can do to match the class labels to the sampling.
Is this what you mean? :
%
shuffle = randperm(1000);
sample = sample(shuffle,:);
%
idx = [a ; p];
K1 = Book2(idx (shuffle), :);