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

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.

Related

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

Set specific rows of matrices in cell array to zero without using a for-loop

I'd like to replace a specific number of elements of my cell to zero without using for. For example to replace elements of row 2 in example cell a below: How should I proceed possibly using cellfun?
a=cell(2,3);
cellfun(#(x)(zeros(a{x}(2,:))),a);
It gives the error "Bad cell reference operation".
what if I'd like to make row 2 empty again?
Thanks in advance for any help
The action you want to perform requires an assignment within a function. The only way to achieve this is using eval, which is considered bad practice.
A loop is therefore the best remaining option, if you want to keep everything in one script:
A = {randn(2,3),randn(2,3)};
for ii = 1:numel(A)
A{ii}(2,:) = 0;
end
If you don't bother using multiple files, you can put the assignment in a function:
function [ out ] = setZero( cellarray, rowidx )
out = cellarray;
out(rowidx,:) = 0;
end
and use it as follows:
A = cellfun(#(x) setZero(x,2),A ,'uni',0)
You need to find a transformation that turns a given matrix A to a matrix where the second row is all-zero. Here are three alternatives
A=cellfun(#(x) [x(1,:); zeros(size(x(2,:))); x(3:end,:)], A, 'uni', 0)
and
A=cellfun(#(x) diag(1:size(x,1)~=2)*x, A, 'uni', 0)
and
A=cellfun(#(x) bsxfun(#times, (1:size(x,1))' ~= 2, x), A, 'uni', 0)
The first one is the most robust one because it will handle the cases that your matrix has NaN elements. The second and third alternatives simply multiply the second row by zero. The second achieves this by multiplying it with a diagonal matrix where all diagonal elements are 1 except element (2,2) which is zero. The third alternative achieves this using bsxfun.
This is to demonstrate that you can achieve this without for loops however a simple for loop is much more readable.

Why, if MATLAB is column-major, do some functions output row vectors?

MATLAB is well-known for being column-major. Consequently, manipulating entries of an array that are in the same column is faster than manipulating entries that are on the same row.
In that case, why do so many built-in functions, such as linspace and logspace, output row vectors rather than column vectors? This seems to me like a de-optimization...
What, if any, is the rationale behind this design decision?
It is a good question. Here are some ideas...
My first thought was that in terms of performance and contiguous memory, it doesn't make a difference if it's a row or a column -- they are both contiguous in memory. For a multidimensional (>1D) array, it is correct that it is more efficient to index a whole column of the array (e.g. v(:,2)) rather than a row (e.g. v(2,:)) or other dimension because in the row (non-column) case it is not accessing elements that are contiguous in memory. However, for a row vector that is 1-by-N, the elements are contiguous because there is only one row, so it doesn't make a difference.
Second, it is simply easier to display row vectors in the Command Window, especially since it wraps the rows of long arrays. With a long column vector, you will be forced to scroll for much shorter arrays.
More thoughts...
Perhaps row vector output from linspace and logspace is just to be consistent with the fact that colon (essentially a tool for creating linearly spaced elements) makes a row:
>> 0:2:16
ans =
0 2 4 6 8 10 12 14 16
The choice was made at the beginning of time and that was that (maybe?).
Also, the convention for loop variables could be important. A row is necessary to define multiple iterations:
>> for k=1:5, k, end
k =
1
k =
2
k =
3
k =
4
k =
5
A column will be a single iteration with a non-scalar loop variable:
>> for k=(1:5)', k, end
k =
1
2
3
4
5
And maybe the outputs of linspace and logspace are commonly looped over. Maybe? :)
But, why loop over a row vector anyway? Well, as I say in my comments, it's not that a row vector is used for loops, it's that it loops through the columns of the loop expression. Meaning, with for v=M where M is a 2-by-3 matrix, there are 3 iterations, where v is a 2 element column vector in each iteration. This is actually a good design if you consider that this involves slicing the loop expression into columns (i.e. chunks of contiguous memory!).

How can I extract a 1 dimentional row from a multidimentional matrix

I currently have a 3 dimensional matrix and I want to extract a single row (into the third dimension) from it by index (say matrix(2,1,:)). I initially anticipated that the result of this would be a 1 dimensional matrix however what I got was a 1 by 1 by n matrix. Usually this wouldn't be a problem but some of the functions I'm using don't like 3D matrices. For example see the problem replicated below:
threeDeeMatrix=rand(3,3,3);
oneDeeAttempt=threeDeeMatrix(1,1,:);
norm(oneDeeAttempt)
Which returns the error message:
Error using norm
Input must be 2-D.
This is because oneDeeAttempt is
oneDeeAttempt(:,:,1) =
0.8400
oneDeeAttempt(:,:,2) =
0.0700
oneDeeAttempt(:,:,3) =
0.7663
rather than [0.8400 0.0700 0.7663]
How can I strip these extra dimensions? The only solution I can come up with is to use a loop to manually copy the values but that seems a little excessive.
Using permute to rearrange the matrix
The solution (which I found in the final stages of asking this) is to use permute which rearranges the order of the dimensions (similar to a=a' for 2D matrices). Once the unit dimensions are last they are stripped from the matrix and it becomes 1 dimensional.
oneDee=permute(oneDeeAttempt,[3 1 2]) %rearrange so the previous third dimension is now the first
%the matrix is now 3 by 1 by 1 which becomes 3
Using squeeze to remove leading singleton dimensions
As pointed out by Luis Mendo squeeze will very simply remove these leading singleton dimensions without having to worry about which dimensions are non singleton
oneDee=squeeze(oneDeeAttempt);

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