Table and variable names - matlab - matlab

Suppose I have the following MATLAB code:
clear; clc
Items = {'counter','item1', 'item2', 'item3', 'item4'};
a = rand(8,4);
j = (1:8)';
t = table(j,a(:,1), a(:,2), a(:,3), a(:,4),'VariableNames',Items)
I would like to know if there is a sophisticated way to extend this list if i have e.g. 20 items. Following this code, I should include inside table every single a(:,i), i = 1,...,20, plus I would have to do the same for the Items list. I guess there is a more convenient way than this.

See array2table:
a = rand(8,4);
[l, w] = size(a);
j = 1:l;
Items = cell(1, w + 1);
Items{1} = 'counter';
for ii = 2:length(Items)
Items{ii} = sprintf('item%u', ii - 1);
end
t = array2table([j', a], 'VariableNames', Items);
Edit: It seems like there's a lot of overhead associated with array2table. It's essentially a wrapper for mat2cell so there might be a speed benefit to just using that on its own and skipping all the error checking. Haven't tested it out though.

You can make a cell with all columns in a.
for i=1:size(a,2)
acell{end+1}=a(:,i);
end
and then call
table(j,acell{:},'VariableNames',Items)
Here is an example:
Items = {'counter'};
a = rand(8,6);
j = (1:8)'
acell = [];
for i=1:size(a,2)
acell{end+1}=a(:,i);
Items{end+1}=['item',num2str(i)];
end
t = table(j,acell{:},'VariableNames',Items);

Related

struct variable in matlab overlapping through a for loop

I am running some regression in matlab.
I want to store the varibles nicely through structures.
Here is some code:
clc;
clear;
fruit_names={'Apple','Pear','Melon'};
Predictors.Apple = rand(500,11);
Predictors.Pear = rand(500,11);
Predictors.Melon = rand(500,11);
Returns.Apple = rand(500,1);
Returns.Pear = rand(500,1);
Returns.Melon = rand(500,1);
%%
kk=1;
for d = 1:length(fruit_names)
for i = [1,2,3,4,5,6,12,24,48,60]
for jj = 1:11
K = i;
xinit=[Predictors.(fruit_names{d})(:,jj)];
yinit=Returns.(fruit_names{d});
[b,bint,r,rint,stats] = regress(yinit,xinit);
Stats.(fruit_names{d})(kk+1)=stats(1);
kk=kk+1;%to help with reporting
end
end
end
It honestly my best attempt at a simple example. It does require the Econometrics toolbox if I remember correctly.
The problem I am having is the structure Stats stores the results I need but after the first variables include some useless zeros.
I have posted and deleted an earlier question which suggests removing the (kk,:) variables, but if I do this it only contains the final results not the evolution of results through the for loop.
Its the position of the kk variable that is the problem.
It seems like you need to collect the results from the second two loops.
clc;
clear;
fruit_names={'Apple','Pear','Melon'};
Predictors.Apple = rand(500,11);
Predictors.Pear = rand(500,11);
Predictors.Melon = rand(500,11);
Returns.Apple = rand(500,1);
Returns.Pear = rand(500,1);
Returns.Melon = rand(500,1);
%%
for d = 1:length(fruit_names)
kk=1; %move the kk = 1 variable here.
for i = [1,2,3,4,5,6,12,24,48,60]
for jj = 1:11
K = i;
xinit=[Predictors.(fruit_names{d})(:,jj)];
yinit=Returns.(fruit_names{d});
[b,bint,r,rint,stats] = regress(yinit,xinit);
Stats.(fruit_names{d})(kk+1)=stats(1);
kk=kk+1;%to help with reporting
end
end
end
Enjoy your fruit!

Matlab Linear Regression

I have 4 data sets, and I need to perform linear regression on them. I keep getting errors in the matrices I've entered.
Here's what I tried to do: I entered the four different data sets as matrices and created a for loop that would go through each set of data and perform the same calculations on each one.
Not sure if my for loop will work - I have very very basic matlab knowledge and so any help would be appreciated!!
x{1} = [1; 2; 3];
y{1} = [2; 3; 4];
% Assume the following matrices are similar to the ones above
x{2} = [...];
y{2} = [...];
x{3} = [...];
y{3} = [...];
x{4} = [...];
y{4} = [...];
for i = 1:1:4
z = [ones(size(x(i))) x(i)];
a = z\y(i); % Line with error
St = sum((y(i)-mean(y(i))).^2);
Sr = sum((y(i)-(10^(a(1))*x(i).^a(2))).^2);
r2 = 1-Sr/St;
syx = sqrt(Sr/(length(x(i))-length(a)));
end
this is as suggested in the comments a matter of {} istead of (). Try:
z = [ones(size(x{i})) x{i}];
a = z\y{i};

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)

What is the fastest way of appending an element to an array?

This is a follow-up question to How to append an element to an array in MATLAB? That question addressed how to append an element to an array. Two approaches are discussed there:
A = [A elem] % for a row array
A = [A; elem] % for a column array
and
A(end+1) = elem;
The second approach has the obvious advantage of being compatible with both row and column arrays.
However, this question is: which of the two approaches is fastest? My intuition tells me that the second one is, but I'd like some evidence for or against that. Any idea?
The second approach (A(end+1) = elem) is faster
According to the benchmarks below (run with the timeit benchmarking function from File Exchange), the second approach (A(end+1) = elem) is faster and should therefore be preferred.
Interestingly, though, the performance gap between the two approaches is much narrower in older versions of MATLAB than it is in more recent versions.
R2008a
R2013a
Benchmark code
function benchmark
n = logspace(2, 5, 40);
% n = logspace(2, 4, 40);
tf = zeros(size(n));
tg = tf;
for k = 1 : numel(n)
x = rand(round(n(k)), 1);
f = #() append(x);
tf(k) = timeit(f);
g = #() addtoend(x);
tg(k) = timeit(g);
end
figure
hold on
plot(n, tf, 'bo')
plot(n, tg, 'ro')
hold off
xlabel('input size')
ylabel('time (s)')
leg = legend('y = [y, x(k)]', 'y(end + 1) = x(k)');
set(leg, 'Location', 'NorthWest');
end
% Approach 1: y = [y, x(k)];
function y = append(x)
y = [];
for k = 1 : numel(x);
y = [y, x(k)];
end
end
% Approach 2: y(end + 1) = x(k);
function y = addtoend(x)
y = [];
for k = 1 : numel(x);
y(end + 1) = x(k);
end
end
How about this?
function somescript
RStime = timeit(#RowSlow)
CStime = timeit(#ColSlow)
RFtime = timeit(#RowFast)
CFtime = timeit(#ColFast)
function RowSlow
rng(1)
A = zeros(1,2);
for i = 1:1e5
A = [A rand(1,1)];
end
end
function ColSlow
rng(1)
A = zeros(2,1);
for i = 1:1e5
A = [A; rand(1,1)];
end
end
function RowFast
rng(1)
A = zeros(1,2);
for i = 1:1e5
A(end+1) = rand(1,1);
end
end
function ColFast
rng(1)
A = zeros(2,1);
for i = 1:1e5
A(end+1) = rand(1,1);
end
end
end
For my machine, this yields the following timings:
RStime =
30.4064
CStime =
29.1075
RFtime =
0.3318
CFtime =
0.3351
The orientation of the vector does not seem to matter that much, but the second approach is about a factor 100 faster on my machine.
In addition to the fast growing method pointing out above (i.e., A(k+1)), you can also get a speed increase from increasing the array size by some multiple, so that allocations become less as the size increases.
On my laptop using R2014b, a conditional doubling of size results in about a factor of 6 speed increase:
>> SO
GATime =
0.0288
DWNTime =
0.0048
In a real application, the size of A would needed to be limited to the needed size or the unfilled results filtered out in some way.
The Code for the SO function is below. I note that I switched to cos(k) since, for some unknown reason, there is a large difference in performance between rand() and rand(1,1) on my machine. But I don't think this affects the outcome too much.
function [] = SO()
GATime = timeit(#GrowAlways)
DWNTime = timeit(#DoubleWhenNeeded)
end
function [] = DoubleWhenNeeded()
A = 0;
sizeA = 1;
for k = 1:1E5
if ((k+1) > sizeA)
A(2*sizeA) = 0;
sizeA = 2*sizeA;
end
A(k+1) = cos(k);
end
end
function [] = GrowAlways()
A = 0;
for k = 1:1E5
A(k+1) = cos(k);
end
end

How to extract the sequence matrix elements?

I have a matrix as shown in below:
A=[2;1;8;5;4;7]
now i need to extract the matrix A into 2 parts:
newpoint=[2];
rest=[1;8;5;4;7];
then apply loop again to extract the second column as new point :
newpoint=[1];
rest=[2;8;5;4;7];
Applying loop again to take third column number as new point :
newpoint=[8];
rest=[2;1;5;4;7];
Take the number in row sequence until the last row .
Can someone be kind enough to help.Thanks!
Something like that might do:
for i=1:length(A)
newpoint = A(i);
if i==1
rest = A(i+1:end);
else
if i== length(A);
rest = A(1:end-1);
else
rest=A(1:i-1,i+1:end);
... stuff to do
end
I would go for something like this:
for i = 1:size(A,1)
newpoint = A(i,1)
rest = A;
rest(i) = [];
%# use rest and newpoint
end
Or if you prefer saving all the rest and newpoints in a matrix:
newpoint = zeros(size(A,1),1);
rest = zeros(size(A,1)-1,size(A,1));
for i = 1:size(A,1)
newpoint(i) = A(i,1);
temp = A;
temp(i) = [];
rest(:,i) = temp;
end