How to increase observation value by one? - matlab

I use the following code to find a specific entry in my dataset and set this value to obsNum:
originalSet(strcmp(originalSet.ABC, subset.DEF{row}) & strcmp(originalSet.FGH, task),21) = dataset(obsNum);
However, I would like to increase the current value by obsNum instead of setting it to obsNum, but I can't find a syntax for it. In Java I would simply write +=, but how can I do that in Matlab?

There is no Matlab syntax support for the += operator, you'll need to index into the variable twice:
idx = strcmp(originalSet.ABC, subset.DEF{row}) & strcmp(originalSet.FGH, task);
originalSet(idx,21) = originalSet(idx,21) + dataset(obsNum);

Related

Read specific portions of an excel file based on string values in MATLAB

I have an excel file and I need to read it based on string values in the 4th column. I have written the following but it does not work properly:
[num,txt,raw] = xlsread('Coordinates','Centerville');
zn={};
ctr=0;
for i = 3:size(raw,1)
tf = strcmp(char(raw{i,4}),char(raw{i-1,4}));
if tf == 0
ctr = ctr+1;
end
zn{ctr}=raw{i,4};
end
data=zeros(1,10); % 10 corresponds to the number of columns I want to read (herein, columns 'J' to 'S')
ctr=0;
for j = 1:length(zn)
for i=3:size(raw,1)
tf=strcmp(char(raw{i,4}),char(zn{j}));
if tf==1
ctr=ctr+1;
data(ctr,:,j)=num(i-2,10:19);
end
end
end
It gives me a "15129x10x22 double" thing and when I try to open it I get the message "Cannot display summaries of variables with more than 524288 elements". It might be obvious but what I am trying to get as the output is 'N = length(zn)' number of matrices which represent the data for different strings in the 4th column (so I probably need a struct; I just don't know how to make it work). Any ideas on how I could fix this? Thanks!
Did not test it, but this should help you get going:
EDIT: corrected wrong indexing into raw vector. Also, depending on the format you might want to restrict also the rows of the raw matrix. From your question, I assume something like selector = raw(3:end,4); and data = raw(3:end,10:19); should be correct.
[~,~,raw] = xlsread('Coordinates','Centerville');
selector = raw(:,4);
data = raw(:,10:19);
[selector,~,grpidx] = unique(selector);
nGrp = numel(selector);
out = cell(nGrp,1);
for i=1:nGrp
idx = grpidx==i;
out{i} = cell2mat(data(idx,:));
end
out is the output variable. The key here is the variable grpidx that is an output of the unique function and allows you to trace back the unique values to their position in the original vector. Note that unique as I used it may change the order of the string values. If that is an issue for you, use the setOrderparameter of the unique function and set it to 'stable'

Conditional statement in matlab function argument

I am wondering if its possible to have conditional statements in a function argument.
for ex,
testarray = [1,5,8,5,7,23,61,16]
psum = sum(testarray>2 & testarray<10)
will it possible to implement something like this in matlab.
I would really appreciate an example.
Yes, please see the example below using your data.
testarray = [1,5,8,5,7,23,61,16]; % your array
Find sum of all numbers greater than 2 and less than 10 in testarray
psum = sum(testarray(testarray>2 & testarray<10));
The idea is that you find the indices of the numbers that meet the condition (i.e., testarray>2 & testarray<10 in this case), extract the numbers by indexing into testarray, and then sum them.

Create a CoffeeScript range with a length instead an endpoint?

I want to create a CoffeeScript range (like [4...496]) but using a length instead of an end range. This can be done with a loop like
myNum = getBigNumber()
newArray = ( n + myNum for n in [0...50] )
but I'm wondering if there is range-related shortcut that I'm missing. Is there something like
[getBigNumber()...].length(50) available in CoffeeScript?
You can just do
range = [myNum...myNum + 50]
Edit: As mu points out in the comments, CoffeeScript will add some complexity whether you use the snippet above or the original code. If performance is an issue, it might be better to drop down to plain JS for the loop (using backticks in the CoffeeScript code).
Assuming you want an ascending (i.e. low to high) range, you can do:
myNum = getBigNumber()
length = 50
range = new Array length
i = 0
`for(; i < length ; i++) { range[i] = i + myNum }` # raw, escaped JS
It's a lot faster than CoffeeScript's way of doing things, but note that CoffeeScript's range syntax also supports creating descending ranges by just flipping the boundary values. So CoffeeScript is (as always) easier on the eyes and simpler to work with, but raw JS is 3.5x faster in my test.

Using "who" variable list to open cell array

I am trying to cycle through a list of variables I have say 30+ and calculate the maximum and minimum value for each column in each variable. Save this in a new array and then export to excel.
My thoughts were to use the who function to create an array with the name of all variables which are present. Then cycling through each one using a for loop after working out the size of the array which was created. This works fine, however when I try and use the string to reference the array it does not work.
I will add in the code which I have written hopefully someone will be able to come up with an easy solution :).
variable_list = who
cell2 = input('What cell size do you want to look at? ');
STARTcell = input('What was the start cell size? ');
[num_variables, temp] = size(variable_list);
for va = 1:num_variables
variable = variable_list{va}
[max_value, max_index] = max(variable{cell2/STARTcell})
[min_value, min_index] = min(variable{cell2/STARTcell})
format_values{va} = vertcat(max_values, max_index, min_value, min_index);
end
The variables I am looking at are arrays which is why I use the cell2/STARTcell to reference them.
You need to use the eval() function to be able to get the value of a variable corresponding to a string. For example:
a = 1;
b = 2;
variable_list = who;
c = eval(variable_list{2});
results in c being 2. In your code, the following line needs to change from:
variable = variable_list{va}
to:
variable = eval(variable_list{va});
resulting in variable having the value of the variable indicated by the string variable_list{va}. If variable is of cell type, then you should be fine, otherwise you may have to revise the next two lines of code as well because it seems that you are trying to access the content of a cell.

assigning values to a field of an structure array in MATLAB

I want to replace the value of the fields in a structure array. For example, I want to replace all 1's with 3's in the following construction.
a(1).b = 1;
a(2).b = 2;
a(3).b = 1;
a([a.b] == 1).b = 3; % This doesn't work and spits out:
% "Insufficient outputs from right hand side to satisfy comma separated
% list expansion on left hand side. Missing [] are the most likely cause."
Is there an easy syntax for this? I want to avoid ugly for loops for such simple operation.
Credits go to #Slayton, but you actually can do the same thing for assigning values too, using deal:
[a([a.b]==1).b]=deal(3)
So breakdown:
[a.b]
retrieves all b fields of the array a and puts this comma-separated-list in an array.
a([a.b]==1)
uses logical indexing to index only the elements of a that satisfy the constraint. Subsequently the full command above assigns the value 3 to all elements of the resulting comma-separated-list according to this.
You can retrieve that the value of a field for each struct in an array using cell notation.
bVals = {a.b};
bVals = cell2mat( bVals );
AFAIK, you can't do the same thing for inserting values into an array of structs. You'll have to use a loop.