Algebra function with table and vector

2 views (last 30 days)
Hi guys! I have 1 table (Composition) and 1 vector (S), and I want to compute the following function: Composition(i,j)=Composition(i,j)./S(i)*100.
For this, I tried to use a loop (a and b are the size of Composition and S, respectively):
i = 1;
j = 1;
for i = i:a
for j = j:b
Composition(i,j)= Composition(i,j)./S(i)*100;
j = j+1;
i = i+1;
I get the following error: >> import_excel Undefined operator './' for input arguments of type 'table'.
Error in import_excel (line 73) Composition(i,j)= Composition(i,j)./S(i)*100;
I'm at begginer level, so any help is most appreciated! Thanks!
Ana Castanheiro
Ana Castanheiro on 3 Oct 2016
I'm not sure if I understand your question. I import the excel data using this:
[FileIn,PathIn] = uigetfile('C:\Users\location\*.xlsx',...
FilePath = strcat(PathIn,FileIn);

Sign in to comment.

Accepted Answer

Guillaume on 3 Oct 2016
First, some points not really related to your question:
i = 1;
for i = i:a
While the above will work and do what you want, using the same variable name for the indexing variable and for the start value is really not good practice. Maybe:
istart = 1;
for i = istart:a
but really
for i = 1:a
is simpler.
for i = 1:n
%... do something
i = i+1;
The i = i+1 is completely unnecessary as the for loop will increase i anyway (and you should actually have a warning in the editor). When matlab reaches the end of the loop, it completely ignores any change you've made to the indexing variable and proceeds with the next indexing value regardless.
Please read the documentation about for loops, particularly the examples.
Now, to answer your question. The proper way to access the elements of a table is with {} indexing, not () which returns a smaller table. So, if you do want to use a loop:
for row = 1:height(Composition) %probably the safest way to write the loop
for col = 1:width(Composition)
Composition{row, col} = Composition{row, col} ./ S(row) * 100; %Assuming S is NOT a table
But note that you actually don't need the loop. If using matlab before R2016b:
Composition{:, :} = bsxfun(@rdivide, Composition{:, :}, S(:)) * 100;
And if using R2016b or later, simply:
Composition{:, :} = Composition{:, :} ./ S(:) * 100;

More Answers (2)

Jan Orwat
Jan Orwat on 3 Oct 2016
Edited: Jan Orwat on 3 Oct 2016
If you want to work on tables in MATLAB functions varfun and rowfun come handy.
See following example:
>> a = [1;2;3;4;5;6];
>> b = a+1;
>> c = a*0;
>> T = table(a,b,c)
T =
a b c
_ _ _
1 2 0
2 3 0
3 4 0
4 5 0
5 6 0
6 7 0
>> bsxfun(@plus,T,a)
Undefined function 'bsxfun' for input arguments of type 'table'.
>> varfun(@(col)plus(a,col),T)
ans =
Fun_a Fun_b Fun_c
_____ _____ _____
2 3 1
4 5 2
6 7 3
8 9 4
10 11 5
12 13 6
For your problem, it would look like:
varnames = Composition.Properties.VariableNames; % Store original variable names.
Composition = varfun(@(column)column./S*100, Composition);
Composition.Properties.VariableNames = varnames; % Restore original variable names.

KSSV on 3 Oct 2016
doc xlsread......
Read the data of the excel file using xlsread...then the data will be stored as numbers. You can do all the algebraic operations.
Guillaume on 3 Oct 2016
That is really not a good answer!
The data is stored as numbers, just as a table. The issue has nothing to do with the way the data is read. It's a simple matter of indexing a table.
Since this is linked to the previous question, I would add that rather than using xlsread followed by celltotable, it would be simpler to read the file with:
Composition = readtable(FilePath, 'Sheet1', 'A1:ZZ1');
which will create the table in one go, and use row 1 as the table column name.
readtable is a lot more powerful and flexible than xlsread, so there's really no reason to use xlsread anymore.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!