Dimension mismatch of matrix - matlab

I am not able to save the value of BB in Bv.
MATLAB returns this error:
Subscripted assignment dimension mismatch.
Please help me to do it.
X=[1 6 9 5; 6 36 54 30; 9 54 81 40; 5 30 40 25]
[N1,dim1]=size(X) ;
for i=1:N1
bb=X(i:end,1)*X(i,i:end);
BB=bb(triu(true(size(bb))))
Bv(i,:)=BB(:);
end

As #Rashid suggests, use cell arrays instead of numeric arrays. The beauty of cell arrays is that it can store matrices of different type and size in 1 storage unit. It is much like a structure, but with indices to easily call entries.
X=[1 6 9 5; 6 36 54 30; 9 54 81 40; 5 30 40 25];
for ii=1:size(x,1)
bb=X(ii:end,1)*X(ii,ii:end);
BB=bb(triu(true(size(bb))))
Bv{ii,:}=BB(:);
end
Note that I also changed your loop index to use ii as opposed to i, see here. i is the imaginary unit and to prevent errors it's better to not overwrite build-in functions.
Just an example of how a cell array stores different data types and sizes:
A = magic(2); % 2x2 double
B = uint8(magic(3)); % 3x3 uint8
C = 'hello world'; % string
YourCell{1} = A;
YourCell{2} = B;
YourCell{3} = C;
YourCell =
[2x2 double] [3x3 uint8] 'hello world'
The same but now as a structure:
YourStruct.magic2double = A;
YourStruct.magic3uint8 = B;
YourStruct.MyString = C;
YourStruct =
magic2double: [2x2 double]
magic3uint8: [3x3 uint8]
MyString: 'hello world'
The cell and structure contain the same information, but for information in the cell you call YourCell{ii}, whilst in the structure you must call YourStruct.variablename. The cell can be accessed by indexing, the structure cannot. For the structure however you can use easy names to remember what you stored in each element, whilst that's impossible for the cell.

Related

labelling chunks of data consecutively

I have data contained in 4195X1 double called z1. I would like to extract data in 120 chunks and label them z1_1_120, z1_120_240, z1_240_360, etc using matlab. I would like to both extract them and also label them in this manner in a loop. Here's what I've done so far, but am unsure as to how to proceed:
load(z1)
for i = 1:4195
q=z1(i);
q1(i,:)=q;
q2=q1(1:120:end);
end
z1=q2(1:end);
As Daniel commented, don't do it!
In case you want the kind of labeling you described, you may either use a Table or a Struct data types.
Read the following post:
The solution is easy: Don't do this. It is a shot in your knee
The following solution creates a Table and a Struct.
The Table needs some padding, because all columns must be the same length (and 4195 is not a multiple of 120).
The code is a bit complicated, I tried to solve it without using for loops (for making the solution more efficient [and more interesting]).
I hope you mange to follow the code, and learn from it...
Here is a code sample (explanations are in the comments):
% Fill z1 with sequential numbers (just for testing)
z1 = (1:4195)';
z1_len = length(z1);
% Compute length remainder from 120
len_mod120 = mod(z1_len, 120);
pad_len = mod(120 - len_mod120, 120);
% If length of z1 is not a multiple of 120, add zeros padding at the end.
pad_z1 = padarray(z1, pad_len, 0, 'post'); % After padding, length of z1 is 4120
% Reshape pad_z1 into a matrix where each row is 120 elements
% Z1(:, 1) gets z1(1:120), Z1(:, 2) gets z1(121:240)...
Z1 = reshape(pad_z1, [], length(pad_z1)/120);
% Build naming indices
name_idx = zeros(1, 2*length(pad_z1)/120);
name_idx(1:2:end) = 1:120:length(pad_z1); %First naming index: 1 121 241 361 ...
name_idx(2:2:end) = name_idx(1:2:end) + 120-1; %Second naming index: 120 240 360 480
% String of elements names separated by space
str_names = sprintf('z1_%d_%d ', name_idx); % 'z1_1_120 z1_121_240 z1_241_360 z1_361_480 ...
% Build cell array of names
var_names = split(str_names(1:end-1)); %{'z1_1_120'}, {'z1_121_240'}, {'z1_121_240'}
% Build table, where each column is 120 elements, and column names are 'z1_1_120' 'z1_121_240' 'z1_121_240'
% A table is useful, if you don't care about the zero padding we added at the beginning
% https://www.mathworks.com/matlabcentral/answers/376985-how-to-convert-string-to-variable-name
T = array2table(Z1, 'VariableNames', var_names);
% Convert table to struct:
% S.z1_1_120 holds first 120 elements, S.z1_121_240 holds next 120 elements...
S = table2struct(T, 'ToScalar', true);
% Fix the last field in the stract - should contain only 115 elements (not 120)
S = rmfield(S, var_names{end}); % Remove the last field from the struct
% last_field_name = 'z1_4081_4195'
last_field_name = sprintf('z1_%d_%d', name_idx(end-1), z1_len);
% Add the last field (only 195 elemtns)
S.(last_field_name) = z1(end-len_mod120+1:end);
Table T:
T =
120×35 table
z1_1_120 z1_121_240 z1_241_360 z1_361_480 ...
________ __________ __________ __________
1 121 241 361
2 122 242 362
3 123 243 363
4 124 244 364
5 125 245 365
6 126 246 366
... ... ... ...
Example for accessing the first element: T.z1_1_120(1)
Struct S:
S =
struct with fields:
z1_1_120: [120×1 double]
z1_121_240: [120×1 double]
z1_241_360: [120×1 double]
z1_361_480: [120×1 double]
z1_481_600: [120×1 double]
z1_601_720: [120×1 double]
z1_721_840: [120×1 double]
...
z1_4081_4195: [115×1 double]
Example for accessing the first element: S.z1_1_120(1)

Get the values of an array from indices in another array: Matlab

I have a 20x1 double array A, and a 1000x1 double array B.
I want to get array C, where array C will be 1000x1 double where the values in B are used to index the values in A like so:
C(1) = A(B(1))
C(2) = A(B(2))
...
C(i) = A(B(i))
...
c(1000) = A(B(1000))
How this can be done?
You don't need a loop for this, you can directly use:
C = A(B)
This takes advantage of MATLAB's matrix indexing, which is the way indexing is handled in MATLAB when an array is used instead of an integer.
Take a look at the docs: https://uk.mathworks.com/help/matlab/math/matrix-indexing.html
For example:
A = [11 12 13];
B = [1 2 3 1 2 3 3 2 1];
C = A(B)
C =
11 12 13 11 12 13 13 12 11
Ensure that B only contains integers which are valid indices of A (not less than 1 or greater than the length of A).
I did it using for loop as shown below, not sure if this is the ideal solution:
C = zeros(1000,1);
for i = 1:1000
C(i,1) = A(B(i));
end

Store vectors from structure to matrix without a for loop?

My issue is fairly simple. I have vectors of the same size in a struct (let's call it a.f). Let's say we have 8 structs (8 <1x1 struct>) each containing another structure b which has a vector in it. I'm aware that I can do either this:
for i = 1:8
matrix(i,:) = a(i).f(1:5)
end
or
for i = 1:8
matrix{i} = a(i).f(1:5)
end
Is there another way to store all these arrays into a matrix, without the need for a for loop?
matrix = [a.f];
just stores them all as a vector.
Just use vertcat if your vectors are rows, or horzcat if they are columns.
Example:
>> a(1).f = 1:7;
>> a(2).f = 11:17;
>> matrix = vertcat(a.f)
matrix =
1 2 3 4 5 6 7
11 12 13 14 15 16 17
how about using reshape after [a.f] ? for example:
matrix =reshape([a.f],numel(a),[]);
How about
matrix = zeros(numel(a),numel(a(1).f));
matrix(:) = [a.f];

create sum of cell matrices

I want to have the sum of all matrices stored in a cell array. Currently I do this
StackSummImage = zeros(size(imageList{1}));
for k = 1:stackSize
StackSummImage = StackSummImage + imageList{k};
end
But I would rather want to write it in a single line if possible.
If each of the N images is K x K, you can use cat to concatenate all the images into a K x K x N array, and then sum it along the third dimension:
>> imageList = {[1 2; 3 4], [5 6; 7 8], [9 10; 11 12]};
>> stackSummImage = sum(cat(3,imageList{:}),3)
ans =
15 18
21 24
Edit: You mentioned in the comments that you can't create a single array, because of memory limits. Below is the memory usage profile when I first allocate a 1500x1500x1500 array of doubles (which takes around 30 GB) and deallocate it, followed by allocating a cell array of 1500 arrays, each of which is a 1500x1500 double array. As you can see, the total memory usage is the same in both cases.
This line should do:
StackSummImage = sum([imageList{:}])

MATLAB - Need to split a Matrix into column variables with names sourced from another matrix?

I am new to Matlab and I am having some trouble.
I have two matrices that I obtained via importing data these are 'label' (a cell matrix of text) and 'data' (a matrix of doubles?). I need to be able to create variables relating to each column to allow them to be individually plotted and used in calculations. These variables should be automatically named using text from the label matrix. I can't use textread as these matices vary in size depending on source data
Below is an example of my issue
Data =
1 2 3 4
5 6 7 8
9 10 11 12
label = A B C D
I require some code to make Matlab automatically create variables as follows
A =
1
5
9
B =
2
6
10
etc.
I tried using 'eval' to evaluate my label matrix and then '=' to assign the column, but I get an error message because my data matrix is a 'doubles' matrix not a 'cell' matrix.
Thanks for any help you can offer
I recommend dynamic field names:
Data= [1 2 3 4;
5 6 7 8;
9 10 11 12];
Label={'A','B','C','D'};
for iter=1:length(Label)
DataStruct.(Label{iter})=Data(:,iter);
___________<--- field name created automatically
end
>> DataStruct
DataStruct =
A: [3x1 double]
B: [3x1 double]
C: [3x1 double]
D: [3x1 double]
>> DataStruct.A
ans =
1
5
9
This approach has the advantage that it keeps together(in a conceptual unit) all the data that came from the spreadsheet or other source, and won't accidentally overwrite variables in your workspace if the name of a column happens to already exist as a variable (or even worse, potentially, a function... )
I do agree that its a tricky task....Here is the solution
Data=[1 2 3 4; 5 6 7 8; 9 10 11 12]; % A matrix
label=['A', 'B', 'C', 'D']; % its a cell array
for i=1:numel(label)
v=genvarname(label(i)); % Generating the variable names
eval([v ' = Data(i,:)']); % Assinging values into named variables
end
Hasan's code works well but "label" has to be a cell array and not a vector so you have to write label={'A', 'B', 'C', 'D'} and label{i}. If you want 4 columns write Data(:,i).
Data=[1 2 3 4; 5 6 7 8; 9 10 11 12]; % A matrix
label={'A', 'B', 'C', 'D'}; % its a cell array
for i=1:numel(label)
v=genvarname(label{i}); % Generating the variable names
eval([v ' = Data(:,i)']); % Assinging values into named variables
end