Why does variable stop increasing too early in Matlab loop? - matlab

I have the following code and error. Question follows below:
clear all, close all
%Reading data in from excel
[num,txt,raw] = xlsread('test.xlsx');
%Looking through the raw excel data to find all instances of 'Instruction: '
instructionindex = find(strcmp(raw,'Instruction: '));
%Making an array using a loop that takes the content of each cell in column 2, indexed by instructionindex
instruction = []
for i = 1:numel(instructionindex)
instruction = [instruction; raw{instructionindex(i),2}];
end
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
Error in test2 (line 27)
instruction = [instruction; raw{instructionindex(i),2}];
and in the workspace I can see that while instructionindex is 24 x1 double, i only increases inside the loop to 7. That leads to a value (!) "instruction" of 6 x 5 char. I am not sure if this is somehow related to the fact that the content I am trying to bring together in the array "instruction" are strings.
My question: How can I get all the indexed 24 contents out in array "instruction" and what causes i to stop at 7?
EDIT: To further clarify why I think this is related to cells in column 2 containing strings: If I use
instruction = [instruction; raw{instructionindex(i),4}];
where column 4 contains numbers, everything works fine! I get two vectors of a size 24 each and concatenation works as well.

Related

Assigning arrays to a matrix in a function, syntax problems

I'm having trouble with the syntax in Matlab.
I'm trying to split an audio signal up into different segments (frames).
I would like to return the y-axis values to a matrix (each segment having its own column), and the corresponding time values with each segment having its own row.
I can't even get it to return just one single column and row pair (ie one frame). I just get returned two empty matrices. Here's my code.
function [mFrames, vTimeFrame] = Framing(vSignal,samplingRate,frameLPerc,frameshPerc)
totalTime=size(vSignal,1)/samplingRate
frameLength = totalTime*frameLPerc;
frameShift = totalTime*frameshPerc;
frameNumber =0;
check=frameLPerc;
while check<1
check = check+frameshPerc;
frameNumber=frameNumber+1;
end
start = 1;
% problem part
mFrames = vSignal(round((start:1/samplingRate:frameLength)*samplingRate));
vTimeFrame = round((start:1/samplingRate:frameLength)*samplingRate);
end
In the end I would like to be able to segment my entire signal into mFrames(i) and vTimeFrame(i) with a for-loop, but never mind that I cannot even get my function to return the first one (like I said empty matrix).
I know my segment code should be correct because I've got another script working with the same vSignal (it's a column vector by the way) that works just fine (y==vSignal):
voiced = y(round((1.245:1/Fs:1.608)*Fs));
plot(1.245:1/Fs:1.608,voiced)
I titled this with syntax problems because I'm very new to matlab and am used to Java. It feels very weird not initializing anything, and so I'm unsure whether my code is actually making any sense.
When testing I enter [m1,m2]=Framing(y,16000,0.1,0.05).
I got it.
start was not in the right domain. This is correct:
round((start/samplingRate:1/samplingRate:frameLength)*samplingRate)
When I plot(m2,m1) I now get the correct answer.
I do still have another question though, how can I assign these segments to my matrices?
for i=1:frameNumber
mFrames(:,i) = vSignal(round((start/samplingRate:1/samplingRate:frameLength)*samplingRate));
vTimeFrame(i) = round((start/samplingRate:1/samplingRate:frameLength)*samplingRate);
start=start+frameShift;
frameLength=frameLength+frameShift;
end
I get this error
In an assignment A(I) = B, the number of elements in B and I must be the same.
Like I said I'm trying to get the y-axis numbers in columns next to each other and the x-axis in rows.

Matlab Parse Error with a simple parenthesis?

I'm trying to finish a program and for some reason, the matrix I loaded into Matlab is messing with the ability to select the rows inside it. I'm trying to select all the rows in the matrix and see which values match the criteria for a Live setting. However I can select specific values/sections of the matrix in the command window without issue. Why is this happening? Any ideas?
It appears to only happen when in a for loop, I can do it just fine when it's on its own.
The syntax is: for x = start:stop. I think you are trying to do a for to the whole "A" matrix. You can split "A", according to its format (e.g. if is a table split in two variables).
bye
Richardd is right on; you're trying to iterate on a matrix, no good.
If I read you right, you're trying to run through your A matrix one column at a time, and see all the rows in that column? Assuming that is correct...
Your A matrix is 14x3, so you should go through your for loop 3 times, which is the size of your column dimension. Luckily, there is a function that MATLAB gives you to do just that. Try:
for iColumn = 1:size(A,2)
...
end
The size function returns the size of your array in a vector of [rows, columns, depth...] - it will go as many dimensions as your array. Calling size(A,2) returns only the size of your array in the column dimension. Now the for loop is iterating on columns.

Looping over a Matlab structure

I am currently processing a bunch of files that I have imported into a structure, but have hit a bump in the road while trying to loop over the data.
First of all, here is my structure:
Ice
1.1 az160, az240, az300...
1.1.2 zen15, zen30,zen45...
1.1.2.1 Data
1.1.2.2 Textdata
I am trying to extract a value from each "textdata" cell array and use it to divide a column in data of the same structure. To do so, I am looping through the structure in the following way:
az_names = fieldnames(ice)
for m = 1:numel(az_names)
snames = fieldnames(ice.(az_names{m}))
for k = 1:numel(snames)
inttime = strrep(ice.(az_names{m}).(snames{k}).textdata(9,1), 'Integration > Time (usec): ','');
inttime = strrep(inttime, ' (USB2+E00040)','');
integration = cellfun(#str2num,inttime)
line 17 ice.(az_names{m}).(snames{k}).data(:,4) = ice.(az_names{m}).(snames{k}).data(:,3)/integration
end
end
I get the following error:
Index exceeds matrix dimensions
Edit: Matlab gives me the error at line 17. If I run the code up to "integration" and also write:
ice.(az_names{m}).(snames{k}).data(:,4)
I don't get a problem, Matlab prints to screen the right number and the data column.
I thought this would loop through each field in the structure and do the operation (dividing a column of values by a number), but I seem to be missing a point here. Can anybody see my mistake?
Regards,
If the error occurs when you try to execute this fragment:
ice.(az_names{m}).(snames{k}).data(:,4)
Then the cause is quite simple.
The variables m and k seem to be handled properly (due to the numel in the loop they should never be too big), meaning that the 4 is simply too big.
Check
ice.(az_names{m}).(snames{k}).data(:,4)
Or even more directly
size(ice.(az_names{m}).(snames{k}).data)
And you should find that the second element of the size is less than 4.
On second thought, this fragment works:
a.b=1;
a.b(:,4)=1
So I suspect that the error occurs when trying to read in this part:
ice.(az_names{m}). (snames{k}).data(:,3)
Meaning that the second element of the size should even be less than 3.
Also I would recommend removing the space.

Error with code when run in a loop but none when run outside a loop

Hi and thank you for viewing my question.
I have a large spreadsheet (over 650,000 rows) that I am trying to spit up into separate parts of a structure. I am trying to split it up by the values in one of the columns of which there is 1132 unique text values. The rest of the columns are numerical. I have created a matrix of the numerical values with 4 columns called 'SectionID_Matrix' and a cell array for the text column I want to split the data up by called 'ELR'. I am also trying to name the parts in the structure by the text value I have split them up by. My code is as follows:
ELR_list = unique (ELR);
[m,~]=size(ELR_list);
n = 1;
b = [];
for j = 1:m
x = strcmp(ELR_list(n), char(ELR));
b(:,1) = SectionID_Matrix(x(:,1),1);
b(:,2) = SectionID_Matrix(x(:,1),2);
b(:,3) = SectionID_Matrix(x(:,1),3);
b(:,4) = SectionID_Matrix(x(:,1),4);
t = char(ELR_list(n));
s.(t) = b;
n = n+1;
end
clearvars -except *ELR_list* *ELR* *SectionID_Matrix* *s*
When I run this code though I get an error saying 'Subscripted assignment dimension mismatch'. Error in Sorting_Out_Locations (line 10). b(:,1) = SectionID_Matrix(x(:,1),1);
This is confusing me because when I remove the for loop and manually change the value of n, it works perfectly fine giving me a matrix in the structure with all the rows that contain the nth text value with the name of the text value.
I understand the error is caused by attempting to assign more elements to a section of a matrix or vector than that section can hold but I don't understand where that is happening.
Is there an error in my code that is causing the for loop to fail? because from my limited understanding the loop should just keep going around increase n by 1 each time until it has gone through all of the unique ELR values.
This is my very first time on Matlab (so any pointer on my code are very appreciated) and have spend all afternoon trying to get this working but no amount of internet help or the matlab website is helping.
Thank you for any help
In your code, the first time it runs through the loop, the size of the b matrix is set according to the number of true values in x. The next time it runs through the loop, that may be a different size, so you get the mismatch.
You can just clear b at the end of each loop iteration with b = []
The error Subscripted assignment dimension mismatch appears when you try to insert a matrix of a certain size into a matrix of a different size. For your code, it means that in the line
b(:,1) = SectionID_Matrix(x(:,1),1);
there is an attempted insertion of mismatching sizes: the size of SectionID_Matrix(x(:,1),1) and the size of b(:,1) are not the same. This is most likely because you only take certain values of each column of SectionID_Matrix using the logical indexing of x. To fix this you need the same logical indexing in b:
b(x(:,1),1) = SectionID_Matrix(x(:,1),1);

copy looping matrixes into one 3-d matrix

I have a list of text files that I would like to load, and then extract rows where they all overlap. The first column contains years and each data set spans a different chunk of years but they all overlap in the middle. In the end I would like to have a three dimensional matrix with the overlapping years in one matrix. My code keeps getting stuck at the line that I have commented out. I know its incorrect but could anyone tell me why it is incorrect?
clear all
name_list = {'Beijing';'GT';'soi';'naoi';'Sydney_Airport';'Los Angeles';'Paris';'Presque Isle'};
[m,n] = size(name_list);
files = dir('*.txt');
[m,n] = size(files);
for i=1:m
eval(['load ' files(i).name ' -ascii']);
vals{i} = load(files(i).name);
matrix = vals{i};
station = (files(i).name(1:end-4));
startyear(i) = min(matrix(:,1));
endyear(i) = max(matrix(:,1));
allstart = max(startyear);
allend = min(endyear);
%matrixnew(i) = matrix(allstart:allend,2:13,i);
end
Two problems here:
Your commented line %matrixnew(i) = matrix(allstart:allend,2:13,i); assumes that matrix is a 3-d array, but elsewhere you treat it as 2-d (and I believe that load always returns a 2-d array). This could be why you are getting the "Index exceeds matrix dimensions" error. Example:
>> foo = rand(10,10);
>> foo(2:10,3:4,2)
Index exceeds matrix dimensions.
Maybe you want matrix(allstart:allend,2:13)? But that won't work, because allstart contains a year, which presumably will not be a valid index for the array (a more likely cause of your error). Using the index that contains the smallest value would be closer to being correct, but I think it still won't work.
matrixnew refers to a single element of an array. You can't assign an array to an element of an array. grantnz is right that making matrixnew a cell array would fix this error, and I guess that in the end you could turn your cell array into 3-d array.
I think you are on the right track, but are missing a few pieces to making this work. One thing to consider is that it looks like you are trying to do everything in a single pass. I don't see how that can work. You need to real all files before you can decide which range of years to keep. So do it in multiple passes: first load all data from all files into a cell array, then figure out the range of years, then pull the data from each file for that range of years.