MATLAB - How to append to matrix rows using a forloop - arrays

Im semi-new with matlab, i've been using it in my course for a while now, but never really been taken in by it.
I have a vector of quite a large size, it is a sound file to be accurate. I'm required to take every 128 elements from this vector, and add them to a matrix.
So matrix row 1 will contain the first 128 (1-128) elements, matrix row 2 will contain the second 128 (128-256) etc...
How can I go about doing this? I've looked up the matlab mathworks help files and havent been able to find anything. I know I can append matrices using z = [x,y] but its not working for me...
Appreciate any help, thanks!

You can do this with the reshape command:
>> A = [1 2 3 4 5 6];
>> B = reshape(A, 3, 2)'
B =
1 2 3
4 5 6

Look at the reshape command. If you start with a (N*128 by 1) vector then with reshape(A,[N,128]) you should get a (N by 128) matrix.

As others said reshape command is the right tool for you. But before you start using reshape, you would like to make sure two things:
usually for any sound file there will be some header information, you need to start reading from the file position after the header information. you can find online manuals to get the size of header-data, for example the canonical sound data format can be found here: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
If the format of your sound file is something else then you'll have to find it out.
the number of samples to be read should be either truncated or padded to multiple of 128 since you want a matrix of N*128 size

This can be done slightly more conveniently even, as reshape can compute one of its argument itself
In MarkD's answer:
A = [1 2 3 4 5 6];
B = reshape(A, 3, 2)'
replace the second line with
B = reshape(A, 3, [])'
The [] input tells reshape: determine yourself what this should be (length(A)/3 in your case)

Related

Is there any mechanism to auto squeeze in Matlab / Octave

For an nD array, it would be nice to be able to auto squeeze to remove singleton dimensions. Is there a way to do this that I don't know about? This would be especially useful for aggregate functions (e.g. sum, mean, etc) where you always expect a result with fewer dimensions.
Here's a simple example:
>> A = ones(3,3,3);
>> B = mean(A);
>> size(B)
ans =
1 3 3
>> squeeze(B)
ans =
1 1 1
1 1 1
1 1 1
It would be nice if Matlab/Octave would automatically do the squeezing for me. Or if there was a way to turn that option on (something similar to hold on for plots).
As far as I know, Matlab does not have that. And I don't think it would be a good idea. Consider a modified version of your example:
>> A = ones(3,1,1,3);
>> B = mean(A);
>> size(B)
ans =
1 1 1 3
What should "auto-squeeze" do here? Reduce B to size [1 1 3] or to [1 3]?
You could argue that it should remove the same dimension that mean has turned into a singleton. But then it would have to be done within the mean function, perhaps with an optional input argument. Once you get the function output, there is no information how it was obtained.
Or you could argue that it should remove all singleton dimensions, like squeeze (more or less) does. But then it would remove dimensions that were already singleton in the function input, which is probably unwanted.
If you ask me, having a second input in squeeze specifiyng which (singleton) dimensions to remove would be a nice addition (in the same vein as you can use mean(A, 1) to force the operation to be applied along the first dimension even if A happens to be a row vector).
I agree with Luis and Cris, but I would add the following.
Both Matlab and Octave do automatically squeeze extra dimensions, in a very particular scenario: any dimensions at the end that have been reduced to singletons, are automatically squeezed out.
E.g.
A = ones([1,2,3,4]);
B = mean(A, 4);
size(B)
% ans = 1 2 3
Note, how the answer is [1,2,3], and not [1,2,3,1]. This is in contrast to languages like python, for instance, where a size of (1,1) is very different to a size of (1,).
Therefore, with regard to your questions, one way to use this to your advantage could be to ensure that the dimension that is to be reduced is always found at the end, and thus automatically simplified.
This becomes even more useful when you realise that:
size(A(:)) % ans = 24 1 (i.e. 24)
size(A(:,:)) % ans = 1 24
size(A(:,:,:)) % ans = 1 2 12
size(A(:,:,:,:)) % ans = 1 2 3 4
Meaning, if you order your dimensions hierarchically you can ensure that any operations that need to take place over the higher dimensions, can a) be vectorised easily, and b) give a natural result, without the need to waste time squeezing or permuting the resulting dimensions.

Create an array 1*3 containing only one 1 and rest 0

I am just learning matlab now. I faced a difficulty in creating an array of 3 elements in a row.
I wrote a code
Source = randi ([0,1],1,3);
which gave me output
[1,1,0].....
[0,1,1]....
but I was willing to get only one 1 and two zeros in the output instead of getting two 1 and one zero.
I know I am wrong because I am using randi function and gives random value of 0 & 1 and output I get can be [0,0,1] ... [1,0,0]... too.
My clear problem is to only get only one 1 if I repeat as many times. e.g. I should get only [0,0,1] or [0,1,0] or [1,0,0].
Hope I can get solution.
Thank you.
Ujwal
Here's a way using randperm:
n = 3; %// total number of elements
m = 1; %// number of ones
x = [ones(1,m) zeros(1,n-m)];
x = x(randperm(numel(x)));
Here is a couple of alternative solutions for your problem.
Create zero-filled matrix and set random element to one:
x = zeros(1, 3);
x(randi(3)) = 1;
Create 1x3 eye matrix and randomly circshift it:
x = circshift(eye(1,3), [0, randi(3)]);

Is there a way to quickly extract the parts from a vector without looping?

Consider that I have a vector/array such that it looks as follows:
each part is a sub array of some size fixed and known size (that can only be accessed through indexing, i.e. its not a tensor nor a higher order array). So for example:
x1 = x(1:d);
if d is the size of each sub array. The size of each sub array is the same but it might vary depending on the current x we are considering. However, we do know n (the number of sub arrays) and d (the size of all of the sub arrays).
I know there is usually really strange but useful tricks in matlab to do things more optimized. Is there a way to extract those using maybe indexing and and make a matrix where the rows (or columns) are those parts? as in:
X = [x_1, ..., x_n]
the caveat is that n is a variable and we don't know aprior what it is. We can find what n is, but its not fixed.
I want to minimize the amount of for loops I actually write in matlab to hope its faster...just to add some more context.
First I would consider simple reshaping to keep the output as a simple double matrix
x = (1:15).' %'
d = 3;
out = reshape(x,d,[])
and further on just use indexing to access the columns out(:,idx);
There is no need to know n in advance, as reshape is calculating it based on d and the number of elements in x.
out =
1 4 7 10 13
2 5 8 11 14
3 6 9 12 15
If you'd insist on something like cell arrays, use accumarray with ceil to get the subs:
out = accumarray( ceil( (1:numel(x))/d ).', x(:), [], #(x) {x})

Entering Elements in a 4-D array in the Correct Orientation

In the code below "G" returns a (10*4) matrix which is in the correct orientation.
All I want then is to be able to view/call these (10*4) matrices indexed by (j,k). However when I store the matrix "G" in the 4-D matrix "test" the data is displayed in a way that is a little counter intuitive? When I look at test in the variable editor I get:
val(:,:,1,1) =
1
val(:,:,2,1) =
0
val(:,:,3,1) =
0
val(:,:,4,1) =
0
.
.
.
val(:,:,1,10) =
1
val(:,:,2,10) =
0
val(:,:,3,10) =
0
val(:,:,4,10) =
0
So all the data is there but I want it displayed at a 10*4 matrix?
Also as you will see I had to change the code for "Correl_betas" and transpose "G" to get to where I am above. However I felt I did this by playing around rather than what I thought the code should be doing. Why does the original code not work? I am having to change the order of the 3rd and 4th dimensions when declaring "Correl_betas" and then pass the transpose of G, but this seems totally counter intuitive as the last two dimensions in the original "Correl_betas" and the original (un-transposed) "G" also match? But when I did it this way the ordering seemed even further from the 10*$ matrix I want.
So I have 2 questions?
1.) How can I get to the 2-dimentional (10*4) matrices I want indexed by j,k from where I am?
2.) How come the original code above doesn't result in the last two columns producing (10,4) matrices?
A large part of the problem is that I have very little experience working with matrices that have more than 2 dimensions so sorry if this question shows a lack of understanding. Maybe a pointer to a god tutorial on how to interpret manipulate higher dimensional matrices would help too.
%Correl_betas=zeros(50,50,10,4);
Correl_betas=zeros(50,50,4,10);
mats=[1:10]';
L1=-1;
for j=1:51
L1=L1+1;
L2=-1;
for k=1:51
L2=L2+1;
lambda=[ L1; L2 ];
nObs=size(mats,1);
G= [ones(nObs,1) (1-exp(-mats./lambda(1)))./(mats./lambda(1)) ((1-exp(-mats./lambda(1)))./(mats./lambda(1))-exp(-mats./lambda(1))) ((1-exp(-mats./lambda(2)))./(mats./lambda(2))-exp(-mats./lambda(2)))];
%Correl_betas(j,k,:,:)=G;
Correl_betas(j,k,:,:)=G';
test=Correl_betas(j,k,:,:);
temp1=corrcoef(Correl_betas(j,k,:,2),Correl_betas(j,k,:,3),'rows','complete');
temp2=corrcoef(Correl_betas(j,k,:,2),Correl_betas(j,k,:,4),'rows','complete');
temp3=corrcoef(Correl_betas(j,k,:,3),Correl_betas(j,k,:,4),'rows','complete');
F2_F3(j,k)=temp1(1,2);
F2_F4(j,k)=temp2(1,2);
F3_F4(j,k)=temp3(1,2);
end
end
To reshape the matrix as desired,
val2 = permute(val,[4 3 2 1]);
This brings the 4th dimension (size of 10) onto the first, and the the 3rd dimension (size of 4) onto the second.
In your loop, both j and k cycle through 1:51 so the first two dimensions of Correl_betas will end up being length 51 too.

How to slice array in GUI function?

Because I am trying to let a GUI element slice my array, there will be a : (colon) sign in the variables. This returns me an error:
Error in gui_mainfcn (line 96)
feval(varargin{:});
line 96 refers to this code:
image(handles.data(1:handles.rows,1:handles.cols, temp))
Temp looks like this
temp =
1 1 1 1 2 1 1 1 1
And both handles.rows and cols are the value 64. So the problem seems to be that I use colons in the gui function. However, to slice I need to use colons. My question now is: Any idea how to work around this?
To clarify as requested below
The above code works when I manually enter it in the console. Also when I use handles.data(:,:,1,1,1,1,2,1,1,1,1), handles.data(1:end,1:end,1,1,1,1,2,1,1,1,1), handles.data(1:64,1:64,1,1,1,1,2,1,1,1,1), etc I get the same error from the gui. Manually they all work and return a 64 by 64 array of doubles which I can plot with image().
Might be related to these questions, however those deal with parfor difficulties and dont seem to answer my question:
matlab-parfor-slicing-issue
index-inside-parfor-slicing
I am now also reading the advanced topics for slicing variables. Still dont see what I am doing wrong though, so any help or explanation would still be greatly apprectiated. Thanks!
Explanation
By putting the vector temp as the third index into your data, you are not indexing the higher dimensions - you are repeatedly indexing the third. In other words, you get handles.data(:,:,[1 1 1 1 2 1 1 1 1]) instead of handles.data(:,:,1,1,1,1,2,1,1,1,1).
Solution
Here's a solution that doesn't require squeeze or eval. It exploits the comma-separated lists output of the {:} syntax with cell arrays, and the ability to apply linear indexing on the last subscripted dimension.
ctemp = num2cell(temp); % put each index into a cell
sz = size(handles.data); % i.e. sz = [256 256 1 1 2 1 2]
sliceind = sub2ind(sz(3:end),ctemp{:}); % compute high dim. linear index (scalar)
image(handles.data(:,:,sliceind));
This performs subscripting of a >3D array with only 3 subscripts by computing the last subscript as a linear index. It's weird, but convenient sometimes.
A heads up for people with the same problem, this error can not only result from not knowing how to slice, it could also result from not having defined your variables correctly: http://www.mathworks.nl/matlabcentral/answers/87417-how-to-slice-inside-gui-without-error-feval-varargin

Resources