copy looping matrixes into one 3-d matrix - matlab

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.

Related

How to sum a matrix with unaligned elements?

I am trying to sum in the second dimension a matrix QI in Matlab. The trick is, the columns contain a series of increasing numbers, but not all columns have the same number of elements (i.e. numel(QI(:,1)) ~= numel(QI(:,2)) and so on). For the sake of clarity, I attach a picture of it. Note that I padded the missing areas with 0, so the previous condition becomes nnz(QI(:,1)) ~= nnz(QI(:,2)).
One initial strategy that I thought of was to treat this as an image and construct a mask for each different gradient level, but that seems like a tedious job.
Anyone has a better idea on how to do this? I should also mention that I am able to freely modify how QI is generated, but I'd rather not if there is a solution for this problem.
EDIT:
Hopefully the new colored image should give a better understanding.
FYI, each column was previously stored in a cell array without the trailing zeros. Then I extracted the columns one by one and stored them in a matrix in order to perform the summation, padding the extra zeros whenever the length isn't the same.
Generally these column data should have the same number of rows, but sometimes that's not the case, and even worse, they do not allign properly.
I'm starting to think if it's better to rework the code that generate the cell arrays rather than this matrix. Thoughts?
Thank you,
edit: following you comment, I modified the answer. Be aware that your data cannot be really "aligned" because they have not the same number of value.
A way would be to use a cell as a storage for your measures.
valueMissing = 0; % here you can put the defauld value you want
% transform you matrix in a cell
QICell = arrayfun(#(x) QI(QI(:,x)!=valueMissing,x), 1:size(QI,2),'UniformOutput', false);
Now you can sum the last element of the vectors inside the cell
QIsum = sum(cellfun(#(x) x(end), QICell))
Or reorder the vectors so that your last element are "aligned"
QICellReordered = cellfun(#(x) x(end:-1:1),QICell, 'UniformOutput',false);
Then you can make all possible sums:
m = min(cellfun(#numel, QICellReordered));
QIsum = zeros(m,1);
for i=1:m
QIsum(i) = sum(cellfun(#(x) x(i), QICellReordered));
end
% reorder QISum to your original order
QIsum = QIsum(end:-1:1);
I hope this help !

error importing multiple files at same time

Trying to join different files with an specific suffix in a matrix, but always I obtain a matrix with unique row containing the values of the last file..
As example
I have multiple files like:
2302_Cabeza_L_x.txt, 2202_Cabeza_L_x.txt, 1702_Cabeza_L_y.txt.....
The code I'm using...
codes= [2302,2202,1602,1502,1702];
for p=1:length(codes)
name=mat2str(codes(:,p));
orden2=(name(2:length(name)-11));
orden=str2num(orden2);
allCABLX = importdata([name '_Cabeza_L_x.txt']);
allCABLY = importdata([name '_Cabeza_L_y.txt']);
allCABCY = importdata([name '_Cabeza_C_y.txt']);
allCABCX = importdata([name '_Cabeza_C_x.txt']);
end
Thank you!
You are overwriting the variables allCABLX, allCABLY, allCABCY and allCABCX in every iteration, so only the last values stay there after the loop. You need to save the data inside the loop to be able to access it afterwards.
If all files have the same number of entries, this can be achieved by concatenating the values obtained by importdata. Since I don't know the dimensions of the output of importdata, I'm not going into the details here.
If the files have different number of entries, you can use a cell array to store the data of each iteration. This works as well in case all entries are of the same size. The following code does exactly this for one of the variables:
codes= [2302,2202,1602,1502,1702];
allCABLX = cell(length(codes),1); % create empty cell array
for p=1:length(codes)
name=num2str(codes(:,p));
allCABLX{p} = importdata([name '_Cabeza_L_x.txt']);
end
Note that I replaced mat2str by num2str since you only have a number to convert and not a whole matrix. In case all the files have data of the same dimension, you can use cell2mat after the loop to get a normal matrix.

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.

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);

Unable to replace values in a matrix

I'm currently working on a cellular automata but i keep running into this problem. I have a matrix idxR which contains zero's and/or ones, depending on a probability process:
idxR = ((rRecr>rEmpty)&(rRecr>rAlgae)&(rRecr>rCoral));
Now i want to replace all ones in idxR with unique values and assign it to the variable colonies. I came up with the following:
colonies = idxR;
no = sum(colonies(:)==1)
maxvalue = max(colonies(:));
replace = [1:no]+maxvalue;
ret = reshape(replace,no,1);
colonies(colonies==1) = colonies(colonies==1).*ret;
When i output colonies it gives me a matrix with just ones and zeros and not a matrix where all ones have been replaced with incremental values. I tried this code in a new file and assigned a matrix with random ones and zeros to idxR and then it seems to work. So i guess to problem lies with the matrix idxR in my automata. It might be worth mentioning that idxR is contained in a for loop.
Can somebody tell me how to fix this?
You got the entire logic correct, except one minor flaw. You have idxR as a logical matrix. Hence colonies is a logical matrix too. Therefore, you get the expected output till the second-last line. Problem occurs on the last line, when you try to assign an array of numbers in which each number is greater than 1 (colonies(colonies==1).*ret;) to a logical matrix.
Elements greater than 1 are clipped to one and thus you see only zeros and ones. There is a simple workaround. Change the first line to
colonies = double(idxR);
P.S. The answer was right in front of you, you just didn't spot it. You had written:
I tried this code in a new file and assigned a matrix with random ones and zeros to idxR and then it seems to work.
The idxR matrix must have been of double datatype, if you used randi.
Parag got it right. You have the solution there.
You can use the following code if you are looking for a more "organized" way to get to 'colonies' -
colonies = double(idxR);
maxvalue = max(colonies(:));
ind1 = find(idxR==1);
colonies(ind1)=maxvalue + (1:numel(ind1));