MATLAB string to number error - arrays

I have a dozens of arrays with different array names and I would like to do some mathematical calculations in to for loop array by array. I srucked in calling these array into for loop. Is there anybody can help me with this problem? text1 array contains array names. My "s" struct has all these arrays with the same name content of text1 array.
text1=['s.CustomerArray.DistanceDriven','s.CustomerArray.TimeDriven'];
for i=1:3
parameter=str2num(text1(i));
k=size(parameter,2);
a=100;
y=zeros(a,k);
end
After this part my some other calculations should start using "parameter"
Regards,
Eren

I think you are doing several things wrong, here are some pointers.
Rather than listing them manually, consider looping over the fieldnames which can be obtained automatically.
If you are looping over strings, make sure to use a cell array with , rather than a matrix.
If you have a constant, declare it outside the loop, rather than inside the loop. This won't break the code but just makes for obsolete evaluations.
If you want to store results obtained inside a loop, make sure to add an index to the variable that you loop over.
That being said, here is a guess at what you are trying to do:
f = fieldnames(s.CustomerArray);
y = cell(numel(f),1);
parameter = NaN(numel(f),1);
for t = 1:numel(f)
parameter(t) = s.CustomerArray.(f{t});
y{t} = zeros(100,numel(f{t}));
end

Related

removing second layer for loop when defining array

Working in MATLAB R2017a. I'm trying to optimise a piece of code I'm working on. It uses arrays to store field values on a grid.
In order to create a specific function in a field array I originally used the straight forward method of two for loops iterating over all the array elements. But i know for loops are slow so since then I came back and tried my best to remove them. However I could only manage to remove one of the loops; leaving me with this:
for n = 1:1:K
%%% define initial pertubation
t=n*dt;
% create array for source Ez field.
xtemps = (1:Ng)*dX;
for k = 1:Ng
ztemp = k*dX;
Ez0(k,:) = THzamp * (1/(1+exp(-(t-stepuppos)))) * exp(-((xtemps-...
THzstartx).^2)./(bx^2)) .* (t-((ztemp-THzstartz)/vg))*exp(-((t-((ztemp-...
THzstartz)/vg))^2)/(bt^2));
end
The important bit here is the last 5 lines, but I figured the stuff before might be important for context. I've removed the for loop looping over the x coordinates. I want to vectorize the z/k for loop but I can't figure out how to distinguish between the dimensions with the array oporators.
Edit: THzamp, stepuppos, bx, bt, THzstartz, THzstartx are all just scalars, they control the function (Ez0) I'm trying to create. dX and t are also just scalars. Ez0 is a square array of size Ng.
What I want to achieve is to remove the for loop that loops over k, so that that the values of ztemp are defined in a vector (like xtemps already is), rather than individually in the loop. However, I don't know how I'd write the definition of Ez0 in that case.
First time posting here, if I'm doing it wrong let me know. If you need more info just ask.
It isn't clear if n is used in the other headers and as stated in the comments your sizes aren't properly defined so you'll have to ensure the sizes are correct.
However, you can give this vectorize code a try.
n = 1:K
%%% define initial pertubation
t=n*dt;
% create array for source Ez field.
xtemps = (1:Ng)*dX;
for k = 1:Ng
ztemp = k*dX;
Ez0(k,:) = THzamp .* (1./(1+exp(-(t-stepuppos)))) .* exp(-((xtemps-...
THzstartx).^2)./(bx^2)) .* (t-((ztemp-THzstartz)/vg)).*exp(-((t-((ztemp-...
THzstartz)/vg)).^2)/(bt.^2));
end
So now t has the size K you'll need to ensure stepupposand (ztemp-THzstartz)/vg) have the same size K. Also you can take a look at vectors vs array operators here.

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.

Compare two list of string array

How do I solve, Two string arrays J=(nx1) and K=(mx1), with same values, if some of the values are missing in J then I need to create a new array for those missing values L=(ix1) ; for example:
J={Two_Headlights
one_engine
four_wheels
two_seats
two_seatbelts}
K={Two_Headlights
one_engine
one_gear
one_break
one_clutch
four_wheels
two_seats
two_seatbelts}
then I would like to create a new array for those missing values in J;
L={one_gear
one_break
one_clutch}
I have tried using the for loop by using setdiff and aswell as using strcmp, but I dont know where I am going wrong, I am not able to get the result.
I guess you missed putting the single quotation for the strings when writing your question.
The setdiff(A,B) function will return the data in A that is not in B. So your first argument must be K.
J={'Two_Headlights','one_engine','four_wheels','two_seats','two_seatbelts'};
K={'Two_Headlights','one_engine','one_gear','one_break','one_clutch','four_wheels','two_seats','two_seatbelts'};
L = setdiff(K,J);

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.

Making outputs from an array in Matlab?

I have an array of 20 items long and I would like to make them an output so I can input it into another program.
pos = [0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,]
I would like to use this as inputs for another program
function [lowest1, lowest2, highest1, highest2, pos(1), pos(2),... pos(20)]
I tried this and it does not work is there another way to do this?
I'm a little confused why you'd want to do that. Why would you want 20 outputs when you could just return pos as a single output containing 20 elements?
However, that said, you can use the specially named variable varargout as the last output variable, and assign a cell to it, and the elements of the cell will be expanded into outputs of the function. Here's an example:
function [lowest1, lowest2, highest1, highest2, varargout] = myfun
% First set lowest1, lowest2, highest1, highest2, and pos here, then:
varargout = num2cell(pos);
If what you're trying to do is re-arrange your array to pass it to another Matlab function, here it is.
As one variable:
s=unique(pos);
q=[s(1) s(2) s(end-1) s(end) pos];
otherFunction(q);
As 24 variables:
s=unique(pos); otherFunction(s(1), s(2), s(end-1), s(end), pos(1), pos(2), pos(3), pos(4), pos(5), pos(6), pos(7), pos(8), pos(9), pos(10), pos(11), pos(12), pos(13), pos(14), pos(15), pos(16), pos(17), pos(18), pos(19), pos(20));
I strongly recommend the first alternative.
Here are two examples of how to work with this single variable. You can still access all of its parts.
Example 1: Take the mean of all of its parts.
function otherFunction(varargin)
myVar=cell2mat(varargin);
mean(myVar)
end
Example 2: Separate the variable into its component parts. In our case creates 24 variables named 'var1' to 'var24' in your workspace.
function otherFunction(varargin)
for i=1:nargin,
assignin('base',['var' num2str(i)],varargin{i});
end
end
Hope this helps.
Consider using a structure in order to return that many values from a function. Carefully chosen field names make the "return value" self declarative.
function s = sab(a,b)
s.a = a;
s.b = b;

Resources