I was reading that in MatLab, if you are going to fill a larger matrix, its more computational efficient to declare it's size from before with the use of the cell command; E.g.
X = cell(500,90);
but when I try to add values to it, like
X(i;) = x
where i is vector of double of length 90, and i an integer, I get
conversion from cell to double is not possible
Is my understanding of the cell function correct?
Cell contents are being addressed using curly braces, for example:
X{1,1}=1:8;
cell command creates an empty array:
C = cell(3,4,2);
% Or alternatively:
C{3,4,2} = [];
What you do with the cell array is up to you. But most likely it is not what you want - see Rasman's comment.
Have a look at some more examples either at MathWorks or other tutorials.
Related
In matlab, is it possible to make the iterative variable a cell array? is there a workaround? This is the code I ideally want, but throws errors:
dim={};
a=magic(5);
for dim{1}=1:5
for dim{2}=1:5
a(dim{:})=1; %aimed to be equivalent to a(dim{1},dim{2})=1;
end
end
for dim{1}=1:5
↑
Error: Invalid expression. When calling a function or indexing a variable, use
parentheses. Otherwise, check for mismatched delimiters.
I tested that you cannot have A(1), or A{1} or A.x as index variable. https://www.mathworks.com/help/matlab/ref/for.html doesn't explicitly prohibit that, but it doesn't allow it either.
After very slight changes on your code, this should achieve what you seem to want:
dim={};
a = magic(5);
for dim1=1:5
dim{1} = dim1;
for dim2=1:5
dim{2} = dim2;
a(dim{:})=1; %aimed to be equivalent to a(dim{1},dim{2})=1;
end
end
However, I believe the following is a slightly better solution keeping the spirit of "use a cell array to index in your array":
CV = combvec(1:5,1:5); % get all combinations from (1,1) to (5,5). 2x25 double array. This function is a part of deep learning toolbox. Alternatives are available.
CM = num2cell(CV); % 2x25 cell array. Each element is a single number.
for dim = CM
% dim is a 2x1 cell array, eg {2,3}.
a(dim{:}) = 1; % as above.
end
However, none of these are likely a good solution to the underlying problem.
I wrote a main function in Matlab that calls other functions, each of which produces plots in a new figure. Though each function produces different plots (different colors, number of subplots, and so on) they all share some features (font, fontsize, Linewidth etc.).
In order to make it easier to modify the aforementioned shared parameter for all the MATLAB figures, I have defined in the preamble of the main function a structure variable as follows:
var.font = 'Arial Unicode MS';
var.fontsize = 13;
var.interpreter = 'none' ;
and so on for the other fields. When I call the function in this way (providing the structure as input):
function plot1( var , ... )
fig = gcf
fig.Position(3) = var.Position3
fig.Position(4) = var.Position4
end
everything works fine and the functions apply the feature to each figure. But if I try to provide a variable number of input to the functions using varargin, in this way
function plot1( varargin )
fig = gcf;
temp = varargin(1);
fig.Position(3) = temp.Position3;
fig.Position(4) = temp.Position4;
end
The following error message is prompted "Struct contents reference from a non-struct array object."
You're indexing the cell array incorrectly (this is easily done).
Round parentheses ( ) give you a cell output when indexing a cell array - i.e. your temp is a 1x1 cell with the struct inside it.
You need curly braces { } to extract the contents of a cell array.
Fix: use curly braces:
temp = varargin{1};
I sometimes think of cell arrays as a group of boxes, since each element (or "box" in this analogy) can basically contain anything. To extract a subset of boxes, use round parentheses. To extract the contents of the boxes, use braces. This analogy extends also to tables, where the notation is consistent.
Here's some docs on indexing cell arrays, where the difference is described in more detail:
https://uk.mathworks.com/help/matlab/matlab_prog/access-data-in-a-cell-array.html
I have a griddedInterpolant F and some of the input variables are in a cell array form. As an example, this is how I created the interpolant F:
[x,y,z] = ndgrid(-5:1:5);
t = x+y+z;
mycell = {x,y};
F = griddedInterpolant(mycell{:},z,t);
In reality, the size of the cell array mycell changes each time I run the code, and that's why I figured I have to use a cell array as an input. Now I'd like to call this function with the same input structure. When I have a single row for each input, everything works fine as in the following example:
testcell = {1,3};
F(testcell{:},5)
ans =
9
However, when I'd like the inputs in a vector form, the interpolant doesn't work and I get the following error:
testcell = {1,3; 2, 4};
F(testcell{:,:},[5;1])
Error using griddedInterpolant/subsref
Invalid arguments specified in evaluating the interpolant.
Because I don't know the dimensions (number of columns) in my actual cell array, I can not break testcell apart. What is the right way to use the interpolant F in this case? I could, of course, use a for loop but this approach might be very time consuming due to the large number of data that I have.
I got an answer to my problem in another forum. Apparently, this problem is solved just by slightly fixing how testcell is defined at the end as such:
testcell = {[1;2]; [3; 4]};
I am working with a 400x1200 imported table (readtable generated from an .xls) which contains strings, doubles, dates, and NaNs. Each column is typed consistently. I am looking for a way to locate all instances in the table of any given string ('Help me please') and replace them all with a double (1). Doing this in Matlab will save me loads of work making changes to the approach used on the rest of this project.
Unfortunately, all of the options I've looked at (regexp, strrep, etc) can only take a string as a replacement. Strfind was similarly unhelpful, because of the typing across the table. The lack of cellfun has also made this harder than it should be. I know the solution should have something to do with finding the indices of the strings I want and then just looping DataFile{subscript} = [1], but I can't find a way to do it.
First you should transform your table at a cell array.
Then, you can use the strrep along with str2num, e.g.
% For a given cell index
strrep(yourCellIndexVariable, "Help me please", "1");
str2num(yourCellIndexVariable);
This will replace the string "Help me please" with the string "1" (the strrep function) and the str2num will change the cell index to the double value according to the string.
By yourCellIndexVariable I mean an element from the cell array. There are several ways to get all cells from a cell array, but I think that you have solved that part already.
What you can do is as follows:
[rows, cols] = size(table); % Get the size of your table
YourString = 'Help me please'; % Create your string
Strmat = repmat(YourString,rows,cols); % Stretch to fill a matrix of table size
TrueString = double(strcmp(table,Strmat)); % Compares all entries with one another
TrueString now contains logicals, 1 where the string 'Help me please' is located, and 0 where it is not.
If you have a table containing multiple classes it might be handy to switch to cells though.
Thank you very much everyone for helping think through to a solution. Here's what I ended up with:
% Reads data
[~, ~, raw] = xlsread ( 'MyTable.xlsx');
MyTable = raw;
% Makes a backup of the data in table form
MyTableBackup = readtable( 'MyTable.xlsx' );
% Begin by ditching 1st row with variable names
MyTable(1,:) = [];
% wizard magic - find all cells with strings
StringIndex = cellfun('isclass', MyTable, 'char');
% strrep goes here to recode bad strings. For example:
MyTable(StringIndex) = strrep(MyTable(StringIndex), 'PlzHelpMe', '1');
% Eventually, we are done, so convert back to table
MyTable = cell2table(MyTable);
% Uses backup Table to add variable names
% (the readtable above means the bad characters in variable names are already escaped!)
MyTable.Properties.VariableNames = MyTableBackup.Properties.VariableNames;
This means the new values exist as strings ('1', not 1 as a double), so now I just str2double when I access them for analysis. My takeaway - Matlab is for numbers. Thanks again all!
I'm using matlab and am quite new to it. I'm used to Java and other langauges.
Some background: I'm manipulating images, I work with the imread, imshow etc. commands. I want to store multiple images in an array.
So what I do is
img_list = zeroes(num_images, 1200, 1600, 3) % height,width,RGB
and then I load the images with img_list(i,:,:,:) = my_image; iteratively. That is all working fine.
Now I can display the images as I want by doing imshow(squeeze(img_list(1,:,:,:))). I can't stand this. I would like something as simple as imshow(img_list(1)).
Any idea how I can do this?
I definetly am open to change the type of img_list. Any hints is appreciated. Maybe I could do something so all my images in img_list don't have to be of the same size?
Thanks in advance. :)
The easiest solution would be to use a cell array. Each element of a cell array is a container that can hold a variable of any type and size. You access the element of a cell array as array(i) (which returns a 1-by-1 cell). To access the contents of an element of a cell array, you use curly brackets, i.e array{i}. Also have a look at CELLFUN, which allows you to perform operations on each image.
%# initialize the cell array
img_list = cell(num_images);
%# add an image to the cell array
img_list{4} = someImage;
%# display the image
imshow(img_list{4})
%# display only the red channel
imshow(img_list{4}(:,:,3))
Using cell arrays, as Jonas suggested, is probably the Right Thing -- especially if you want to be able to have images of different sizes. But it's worth mentioning that you can make the simple 4-dimensional-array approach a little nicer: make the image number the last index instead of the first. Then you can say img_list(:,:,:,i) = my_image; and imshow(img_list(:,:,:,1)); with no need for squeezing. That's probably a little better for memory locality (hence for performance) too, though it won't be any better than using cell arrays.
Define a local anonymous function:
% Get image list from somewhere.
img_list = ...;
% ...
% Easy-access to individual frames.
nth_image = #(k) squeeze(img_list(k,:,:,:));
image_count = size(img_list,1);
% Loop over images.
% ...
This allows you to write the following list:
% Process each image.
for i = 1 : image_count,
img = nth_image(i);
% ...
end
If you have multiple image lists or this pattern occurs often, you can write more generic functions:
function [ img ] = get_nth_image ( img_list, k )
img = squeeze(img_list(k,:,:,:));
end
function [ img_list ] = set_nth_image ( img_list, img, k )
img_list(k,:,:,:) = img;
end