What is the point of cell indexing in MATLAB - arrays

The point of indexing is mainly to get the value. In MATLAB,
for a cell array, there is content indexing ({}), and thus cell indexing (()) is only for selecting a subset from the cell array, right?
Is there anything other advanced usage for it? Like using it as
a pointer and pass it to a function?

There is a heavily simplified answer. {}-indexing returns you the content, ()-indexing creates a subcell with the indexed elements. Let's take a simple example:
>> a=x(2)
a =
[2]
>> class(a)
ans =
cell
>> b=x{2}
b =
2
>> class(b)
ans =
double
Now continue with non-scalar elements. For the ()-indexing everything behaves as expected, you receive a subcell with the elements:
>> a=x(2:3)
a =
[2] [3]
The thing really special to Matlab is using {}-indexing with non-scalar indices. It returns a Comma-Separated List with all the contents. Now what is happening here:
>> b=x{2:3}
b =
2
The Comma-Separated List behaves similar to a function with two return arguments. You want only one value, only one value is assigned. The second value is lost. You can also use this to assign multiple elements to individual lists at once:
>> [a,b]=x{2:3} %old MATLAB versions require deal here
a =
2
b =
3
Now finally to a very powerful use case of comma separated lists. Assume you have some stupid function foo which requires many input arguments. In your code you could write something like:
foo(a,b,c,d,e,f)
Or, assuming you have all parameters stored in a cell:
foo(a{1},a{2},a{3},a{4},a{5},a{6})
Alternatively you can call the function using a comma separated list. Assuming a has 6 elements, this line is fully equivalent to the previous:
foo(a{:}) %The : is a short cut for 1:end, index the first to the last element
The same technique demonstrated here for input arguments can also be used for output arguments.
Regarding your final question about pointers. Matlab does not use pointers and it has no supplement for it (except handle in oop Matlab), but Matlab is very strong in optimizing the memory usage. Especially using Copy-on-write makes it unnecessary to have pointers in most cases. You typically end up with functions like
M=myMatrixOperation(M,parameter,parameter2)
Where you input your data and return it.

Related

Slicing Multidimensional Array by a variable

I am writing a method which accepts a two dimensional array of doubles and an int row number as parameters and returns the highest value of the elements in the given row.
it looks like this:
function getHighestInRow(A, i)
return(maximum(A[:i,:]))
end
the issue i am having is when i slice the array with
A[:i,:]
I get an argument error because the :i makes i get treated differently.
the code works in the other direction with
A[:,i,:]
Is there a way to escape the colon? so that i gets treated as a variable after a colon?
You're doing something strange with the colon. In this case you're using the symbol :i not the value of i. Just getHighestInRow(A,i) = maximum(A[i,:]) should work.
Edit: As Dan Getz said in the comment on the question, getHighestInRow(A,i) = maximum(#view A[i,:]) is more efficient, though, as the slicing will allocate a temporary unnecessary array.

How to define and access array in GNUplot?

This is rather easy question or maybe too easy question. But i tried to find the way to done these already and could not find even in GNUplot document. Might be my mistake or misunderstood something about array concept in GNUplot. My question is How to define and access array in GNUplot?
Please just provide easy example of array declaration, assign value of array over loop. i think that's enough and i think this will be useful for other people too.
If you are using Gnuplot 5.1 or superior and need a 1-d array, you simply define the array with size N, remembering that the indices go from 1 to N:
gnuplot> array A[3] #Array definition
gnuplot> A[1]=2
gnuplot> A[3]=4
gnuplot> print A[1]
2
gnuplot> print A #Print the array, with empty A[2]
[2,,4]
If you need more than one dimension or are using previous versions of Gnuplot, you can do the following:
Since there are no vector variables in previous versions of Gnuplot, two functions can be defined to get and set values to a behind the scenes variable whose name include the index. The functions are:
aGet(name, i) = value(sprintf("_%s_%i", name, i))
aSet(name, i, value) = sprintf("_%s_%i = %.16e", name, i, value)
To assign and retrieve values on the array A you do
eval aSet("A",2,3)
print aGet("A",2)
What these functions do is to access a variable called _A_2.
You can build similar function to work with matrices:
mGet(name, i, j) = value(sprintf("_%s_%i_%i", name, i, j))
mSet(name, i, j, value) = sprintf("_%s_%i_%i = %.16e", name, i, j, value)
(This answer will be obsolete with the next stable gnuplot release, as the 5.1 development tree now has native support for array variables.)
(The "splot" command in gnuplot uses the keyword "array" to define the size of NxM matrix that contains function values for a 3D plot. Nothing to do with array variables.)
Arrays like what a programmer knows from C, Pascal, Python, etc. do not exist in gnuplot today (gp5.0). They might get implemented one day, because they'd be highly useful to plot a family of curves with arbitrary (e.g. fitted) parameters.
If you are desperate about arrays in gnuplot, you can (ab)use the word() function (and other string functions) to achieve a somewhat limited substitute. It's also a bit cumbersome:
array = ""
f(a,x) = a*x
do for [i=1:5] {array = array.sprintf(" %.3f",i+rand(0)) }
print "array = ".array
set xr [0:]; set yr [0:30]
plot for [i=1:5] f(word(array,i),x) title word(array,i)." x"
This example writes a set of random numbers to a string variable named "array", and afterwards uses it to plot five linear functions that use the numbers in "array" for their slope. It's handy here that gnuplot autopromotes strings to numerics if used e.g. in an equation.
Inspired by #Karl 's answer, it looks even more like an array when putting the word function into another function:
array(n) = word("1 2 3 4 5 6 7 8 9", n)
print array(3)
This prints 3. So the indexing is one-based.
"Multiply" the array by 2:
print (b="", sum[i=1:9](b=b.(array(i)*2)." ", 0), b)
This prints 2 4 6 8 10 12 14 16 18. Here the sum function is (ab)used to loop over the array and its result is ignored.
And here is shorter, through less generic variant of #bmello's answer:
A_1=1.1; A_2=2.2; A_3=3.3
A(i) = value("A_".i)
print A(3)
For me it feels more intuitiv. The underscore _ can be seen simply as the set function. Also it is not limited to integer indices. Strings are also possible which give some dictionary-like behaviour.

Usage of empty array allocation for custom class

Say, we have a class Car
classdef Car < handle
properties
wheels = 4;
end
methods
function obj = Car()
end
end
end
We can create ten cars like so
cars = Car.empty();
for ii = 1:10
cars(end+1) = Car;
end
However, one can make an empty array of cars first
>> cars = Car.empty(0,10)
cars =
0x10 Car array with properties:
wheels
What I do not understand: If one now puts a single car in it, the array seems to shrink to a single element
>> cars(1) = Car
cars =
Car with properties:
wheels: 4
So, does allocating such an empty array make any sense? What are the use cases?
First of all, note that your question is not directly related to custom classes - you can do this with any MATLAB variable type. For example,
>> a = double.empty(0,10)
a =
Empty matrix: 0-by-10
So your questions are
What I do not understand: If one now puts a single car in it, the array seems to shrink to a single element
Well no, it has grown to a single element. I guess there is an ambiguity here, in that you might expect it to grow not to a 1x1 array but to a 1x10 array, with the other nine elements that weren't directly assigned being set to default (i.e. zero in the case of doubles or other numbers, or to a default element in the case of a custom class). However, I think the only thing to say there is that that's not what MATLAB does.
does allocating such an empty array make any sense? What are the use cases?
The use cases are very few in general, really just edge cases. The capability of having arrays of with zero-length dimensions is obviously required to be there for consistency, but an array of 0x10 is rarely much different in behaviour from an array of 0x0.
If I have an array that may vary in height but will always be 10 wide, I might predefine it as 0x10 rather than 0x0, just to leave myself a reminder in the code of that fact.
Also note that there are differences in behaviour between [] and double.empty(0,0). For example
>> a = rand(4,2)
a =
0.83625 0.19468
0.58508 0.12698
0.44332 0.8509
0.51858 0.3673
>> a(2,:) = []
a =
0.83625 0.19468
0.44332 0.8509
0.51858 0.3673
>> a(2,:) = double.empty(0,0)
Subscripted assignment dimension mismatch.
>> a(2,:) = double.empty(0,2)
Improper assignment with rectangular empty matrix.
This is because = [] is a special piece of MATLAB syntax that is used for deleting rows, rather than literally constructing the empty array and then assigning it. So there's another use case there, i.e. preventing accidental deletion of rows.
This is not a problem related to object programming but a normal behavior which is more general in Matlab.
For instance:
>> a = NaN(0,10);
>> a(1) = 5;
>> a
a =
5
When you define an array of size 0xn Matlab does not allocate any memory to it, since there is no element. So a call to empty(0,10) should not be considered as a pre-allocation.
When you define the first element of the array, you force a resizing, and during resizing Matlab always adopts the minimal possible size for the array.
The empty syntax is useful to define an array that will be filled by aggregation in a loop with the end+1 syntax, for instance:
a = NaN(0,2);
for i = 1:10
a(end+1,:) = [i i^2];
end
Best,

indexed object dot notation method gives scalar property

I'm seeing an issue when I try and reference an object property after having used a dot notation to apply a method.
it only occurs when I try to index the initial object
classdef myclassexample
properties
data
end
methods
function obj = procData(obj)
if numel(obj)>1
for i = 1:numel(obj)
obj(i) = obj(i).procData;
end
return
end
%do some processing
obj.data = abs(obj.data);
end
end
end
then assigning the following
A = myclassexample;
A(1).data= - -1;
A(2).data = -2;
when calling the whole array and collecting the property data it works fine
[A.procData.data]
if i try and index A then i only get a scalar out
[A([1 2]).procData.data]
even though it seems to do fine without the property call
B = A([1 2]).procData;
[B.data]
any ideas?
I would definitely call this a bug in the parser; A bug because it did not throw an error to begin with, and instead allowed you to write: obj.method.prop in the first place!
The fact that MATLAB crashed in some variations of this syntax is a serious bug, and should definitely be reported to MathWorks.
Now the general rule in MATLAB is that you should not "index into a result" directly. Instead, you should first save the result into a variable, and then index into that variable.
This fact is clear if you use the form func(obj) rather than obj.func() to invoke member methods for objects (dot-notation vs. function notation):
>> A = MyClass;
>> A.procData.data % or A.procData().data
ans =
[]
>> procData(A).data
Undefined variable "procData" or class "procData".
Instead, as you noted, you should use:
>> B = procData(A): % or: B = A.pocData;
>> [B.data]
FWIW, this is also what happens when working with plain structures and regular functions (as opposed to OOP objects and member functions), as you cannot index into the result of a function call anyway. Example:
% a function that works on structure scalar/arrays
function s = procStruct(s)
if numel(s) > 1
for i=1:numel(s)
s(i) = procStruct(s(i));
end
else
s.data = abs(s.data);
end
end
Then all the following calls will throw errors (as they should):
% 1x2 struct array
>> s = struct('data',{1 -2});
>> procStruct(s).data
Undefined variable "procStruct" or class "procStruct".
>> procStruct(s([1 2])).data
Undefined variable "procStruct" or class "procStruct".
>> feval('procStruct',s).data
Undefined variable "feval" or class "feval".
>> f=#procStruct; f(s([1 2])).data
Improper index matrix reference.
You might be asking yourself why they decided to not allow such syntax. Well it turns out there is a good reason why MATLAB does not allow indexing into a function call (without having to introduce a temporary variable that is), be it dot-indexing or subscript-indexing.
Take the following function for example:
function x = f(n)
if nargin == 0, n=3; end
x = magic(n);
end
If we allowed indexing into a function call, then there would be an ambiguity in how to interpret the following call f(4):
should it be interpreted as: f()(4) (that is call function with no arguments, then index into the resulting matrix using linear indexing to get the 4th element)
or should it interpreted as: f(4) (call the function with one argument being n=4, and return the matrix magic(4))
This confusion is caused by several things in the MATLAB syntax:
it allows calling function with no arguments simply by their name, without requiring the parentheses. If there is a function f.m, you can call it as either f or f(). This makes parsing M-code harder, because it is not clear whether tokens are variables or functions.
parentheses are used for both matrix indexing as well as function calls. So if a token x represents a variable, we use the syntax x(1,2) as indexing into the matrix. At the same time if x is the name of a function, then x(1,2) is used to call the function with two arguments.
Another point of confusion is comma-separated lists and functions that return multiple outputs. Example:
>> [mx,idx] = max(magic(3))
mx =
8 9 7
idx =
1 3 2
>> [mx,idx] = max(magic(3))(4) % now what?
Should we return the 4th element of each output variables from MAX, or 4th element from only the first output argument along with the full second output? What about when the function returns outputs of different sizes?
All of this still applies to the other types of indexing: f()(3)/f(3), f().x/f.x, f(){3}/f{3}.
Because of this, MathWorks decided avoid all the above confusion and simply not allow directly indexing into results. Unfortunately they limited the syntax in the process. Octave for example has no such restriction (you can write magic(4)(1,2)), but then again the new OOP system is still in the process of being developed, so I don't know how Octave deals with such cases.
For those interested, this reminds me of another similar bug with regards to packages and classes and directly indexing to get a property. The results were different whether you called it from the command prompt, from a script, or from a M-file function...

Matlab array of struct : Fast assignment

Is there any way to "vector" assign an array of struct.
Currently I can
edges(1000000) = struct('weight',1.0); //This really does not assign the value, I checked on 2009A.
for i=1:1000000; edges(i).weight=1.0; end;
But that is slow, I want to do something more like
edges(:).weight=[rand(1000000,1)]; //with or without the square brackets.
Any ideas/suggestions to vectorize this assignment, so that it will be faster.
Thanks in advance.
This is much faster than deal or a loop (at least on my system):
N=10000;
edge(N) = struct('weight',1.0); % initialize the array
values = rand(1,N); % set the values as a vector
W = mat2cell(values, 1,ones(1,N)); % convert values to a cell
[edge(:).weight] = W{:};
Using curly braces on the right gives a comma separated value list of all the values in W (i.e. N outputs) and using square braces on the right assigns those N outputs to the N values in edge(:).weight.
You can try using the Matlab function deal, but I found it requires to tweak the input a little (using this question: In Matlab, for a multiple input function, how to use a single input as multiple inputs?), maybe there is something simpler.
n=100000;
edges(n)=struct('weight',1.0);
m=mat2cell(rand(n,1),ones(n,1),1);
[edges(:).weight]=deal(m{:});
Also I found that this is not nearly as fast as the for loop on my computer (~0.35s for deal versus ~0.05s for the loop) presumably because of the call to mat2cell. The difference in speed is reduced if you use this more than once but it stays in favor of the for loop.
You could simply write:
edges = struct('weight', num2cell(rand(1000000,1)));
Is there something requiring you to particularly use a struct in this way?
Consider replacing your array of structs with simply a separate array for each member of the struct.
weights = rand(1, 1000);
If you have a struct member which is an array, you can make an extra dimension:
matrices = rand(3, 3, 1000);
If you just want to keep things neat, you could put these arrays into a struct:
edges.weights = weights;
edges.matrices = matrices;
But if you need to keep an array of structs, I think you can do
[edges.weight] = rand(1, 1000);
The reason that the structs in your example don't get initialized properly is that the syntax you're using only addresses the very last element in the struct array. For a nonexistent array, the rest of them get implicitly filled in with structs that have the default value [] in all their fields.
To make this behavior clear, try doing a short array with clear edges; edges(1:3) = struct('weight',1.0) and looking at each of edges(1), edges(2), and edges(3). The edges(3) element has 1.0 in its weight like you want; the others have [].
The syntax for efficiently initializing an array of structs is one of these.
% Using repmat and full assignment
edges = repmat(struct('weight', 1.0), [1 1000]);
% Using indexing
% NOTE: Only correct if variable is uninitialized!!!
edges(1:1000) = struct('weight', 1.0); % QUESTIONABLE
Note the 1:1000 instead of just 1000 when indexing in to the uninitialized edges array.
There's a problem with the edges(1:1000) form: if edges is already initialized, this syntax will just update the values of selected elements. If edges has more than 1000 elements, the others will be left unchanged, and your code will be buggy. Or if edges is a different type, you could get an error or weird behavior depending on its existing datatype. To be safe, you need to do clear edges before initializing using the indexing syntax. So it's better to just do full assignment with the repmat form.
BUT: Regardless of how you initialize it, an array-of-structs like this is always going to be inherently slow to work with for larger data sets. You can't do real "vectorized" operations on it because your primitive arrays are all broken up in to separate mxArrays inside each struct element. That includes the field assignment in your question – it is not possible to vectorize that. Instead, you should switch a struct-of-arrays like Brian L's answer suggests.
You can use a reverse struct and then do all operations without any errors
like this
x.E(1)=1;
x.E(2)=3;
x.E(2)=8;
x.E(3)=5;
and then the operation like the following
x.E
ans =
3 8 5
or like this
x.E(1:2)=2
x =
E: [2 2 5]
or maybe this
x.E(1:3)=[2,3,4]*5
x =
E: [10 15 20]
It is really faster than for_loop and you do not need other big functions to slow your program.

Resources