Octave: apply given mapping to cell array - matlab

Imagine I have a cell array "list of lists" in Octave:
octave:6> a = {[1], [3,4], [5,6,7], [8,9,10,11]}
a =
{
[1,1] = 1
[1,2] =
3 4
[1,3] =
5 6 7
[1,4] =
8 9 10 11
}
Now I want to extract a given element from each of the nested rows and the index of each of them is given in a list. E.g. [1, 2, 2, 3] would mean return [1, 4, 6, 10].
What is the best Octave-ish way to do this? I know how to do that with a loop, but that seems ugly...

It seems I have found the solution that is good to me. I realized that cellfun() takes a number of arguments so I can perform the element-wise mapping easily.
octave:31> cellfun(#(x,y) x(y), a, {1,2,2,3})
ans =
1 4 6 10

Related

Matlab Matrixaddress [duplicate]

This question already has answers here:
How to obtain the mirror image of an array (MATLAB)?
(4 answers)
Closed 2 years ago.
During my course I came across that expression:
A(:,end:-1:1)
I have trouble to understand and read the morphemic structure of the 2nd Operand "end;-1;1"
Lets take the example:
A=[1 2 3; 4 5 6; 7 8 9]
I am aware of:
A(:).. Outputs [1 2 3; 4 5 6; 7 8 9] as rows. Operator is :.
A(1,:).. Outputs [1 2 3; 4 5 6; 7 8 9] as columns Operator is , then , .
A(:,1).. Outputs [1 2 3; 4 5 6; 7 8 9] as rows. Operator is , beforehand : .
A(:,end:-1:1)
Output in Matlab show me: 3x3 Matrix.
How am I supposed to read the structure?
Graphem: : ..show me the rows,
Graphem: end:-1 .. ??
Graphem: :1 ..
Somehow ":" was for me the operator for show all of the elements.
It makes sense to me that the "Operand1 , Operand2" shows me the 2 Dimensional Matrix.
First Idea:
The end:-1:1 expression seemed to me like a loop. So -1, 0, 1 => **3x Elements** ?
But when I type
A(1,end:3)
it only shows me the 3rd row.
Second Idea:
A(end:-1:1,1)
It shows me the inverted Matrix..
My background:
I am a undergraduate student from the field of language.
I build in my freetime the 8-Bit Sap1 according Ben Eater.
So I am familiar with program memory or instruction memory.
I understand only the result, but not how it is achieved by the MATLAB compiler.
Someone said to me that the "Matrixaddressing is somehow optimized".
Looking forward to a helpful answer in each step. :)
Thanks in advance!
The end keyword in matrix indexing indicates index of last element in the corresponding dimension. So, A(:,end:-1:1) simply means A(:, size(A, 2):-1:1), which in you example (A=[1 2 3; 4 5 6; 7 8 9]), is equivalent to A(:, 3:-1:1).
But to understand what it does, you need to know what 3:-1:1 does. It creates a subrange. You already know 1:3 creates [1, 2, 3]. 1:3 is simplified form of 1:1:3: rangeStrart:increment:rangeEnd. Now, 3:1 or 3:1:1 creates an empty vector, because rangeStart is greater than rangeEnd. To create [3, 2, 1] you need to use a negative step: 3:-1:1.
So, A(:,end:-1:1) means A(:, [3, 2, 1]), which inverts order of rows of A. Also, A(:,end:3) means A(:, 3:3) and eventually A(:, 3), which returns 3rd row of A.
Edit: about your misunderstandings, addressed by #CrisLuengo
I am aware of:
A(:).. Outputs [1 2 3; 4 5 6; 7 8 9] as rows. Operator is :.
A(1,:).. Outputs [1 2 3; 4 5 6; 7 8 9] as columns Operator is , then , .
A(:,1).. Outputs [1 2 3; 4 5 6; 7 8 9] as rows. Operator is ,beforehand : .
A(3, 2) is the element in the 3,2 position (third row, second column) of A
A(1, :) is equivalent to A(1, 1:size(A, 2)) and A(1, 1:end) and is the first row of A
A(:, 1) is equivalent to A(1:size(A, 1), 1) and A(1:end, 1) and is the first column of A
A(:) is equivalent to A(1:numel(A)) and is a single column containing all elements of A
In MATLAB, when accessing an array, it is accessed as A(row#,col#). row# and col# can either be integers or a vector of integers. If they are integers then one spot in the matrix is accessed. If they are vectors then MATLAB will loop through the vector and choose spots in A which correspond to the integers in the vector.
end:-1:1 creates a vector which contains the integers ranging from the number of columns (in this case because you put this vector in the col section: A(row#,col#)) to 1. Ex: 4x5 matrix, end:-1:1 would be [5 4 3 2 1].
When you put : in the row part of the matrix, that means you access all rows of the matrix.
Here's an example of A(:,end:-1:1)
The col# vector (:) is [1 2 3] and the row# vector (end:-1:1) is [3 2 1]
A = [1 2 3;
4 5 6;
7 8 9]
A(:,end:-1:1)
[3, 5, 7]
I think you're overthinking this slightly.
If we have a vector
A = [1 2 3]
and we call A(end:-1:1), then we get a vector [3 2 1]. The indexing has returned the same vector, with the values reversed. If we now have a matrix
A = [1 2 3; 4 5 6; 7 8 9]
and call A(:, end:-1:1), we get the matrix with the same values in each row, but now the columns have been reversed to give
A(:, end:-1:1) = [3 2 1; 6 5 4; 9 8 7].
Recall what the colon means in this context.
If we define a vector, v = (1:10), we get a vector with the first element being 1, the last element being 10 and each value in between being integers in steps of 1. If we instead define v = (1:2:10), we get the same, but the elements are separated by 2, not 1.
end:-1:1 is a vector made in just the same way. The first number is the final element in the row of A, and the final number is the first element in the row. Each number is separated by a value of -1. If we try
v = 10:-1:1
we get [10 9 8 7 6 5 4 3 2 1]. If we call v(2:4) we get the second, third and fourth elements of v. If we call v(1:end), we simply get v. If we call v(end:-1:1), we return v, with the elements in the reversed order.
Edit A typo.

Order of elements in cell array constructed by accumarray

What I'm trying to do: given a 2D matrix, get the column indices of the elements in each row that satisfy some particular condition.
For example, say my matrix is
M = [16 2 3 13; 5 11 10 8; 9 7 6 12; 4 14 15 1]
and my condition is M>6. Then my desired output would be something like
Indices = {[1 4]'; [2 3 4]'; [1 2 4]'; [2 3]';}
After reading the answers to this similar question I came up with this partial solution using find and accumarray:
[ix, iy] = find(M>6);
Indices = accumarray(ix,iy,[],#(iy){iy});
This gives very nearly the results I want -- in fact, the indices are all right, but they're not ordered the way I expected. For example, Indices{2} = [2 4 3]' instead of [2 3 4]', and I can't understand why. There are 3 occurrences of 2 in ix, at indices 3, 6, and 9. The corresponding values of iy at those indices are 2, 3, and 4, in that order. What exactly is creating the observed order? Is it just arbitrary? Is there a way to force it to be what I want, other than sorting each element of Indices afterwards?
Here's one way to solve it with arrayfun -
idx = arrayfun(#(x) find(M(x,:)>6),1:size(M,1),'Uni',0)
Display output wtih celldisp(idx) -
idx{1} =
1 4
idx{2} =
2 3 4
idx{3} =
1 2 4
idx{4} =
2 3
To continue working with accumarray, you can wrap iy with sort to get your desired output which doesn't look too pretty maybe -
Indices = accumarray(ix,iy,[],#(iy){sort(iy)})
Output -
>> celldisp(Indices)
Indices{1} =
1
4
Indices{2} =
2
3
4
Indices{3} =
1
2
4
Indices{4} =
2
3
accumarray is not guaranteed to preserve order of each chunk of its second input (see here, and also here). However, it does seem to preserve it when the first input is already sorted:
[iy, ix] = find(M.'>6); %'// transpose and reverse outputs, to make ix sorted
Indices = accumarray(ix,iy,[],#(iy){iy}); %// this line is the same as yours
produces
Indices{1} =
1
4
Indices{2} =
2
3
4
Indices{3} =
1
2
4
Indices{4} =
2
3

How do I assign a cell array to multiple matrices?

I am relatively new to matlab, and I was wondering if there was a simpler way to do the following:
Given mycellarray = {[1 2 3 4] [5 6 7 8] [9 10 11 12] [13 14 15 16]}, I would like to assign each matrix inside mycellarray to a separate variable. Is there any faster/better/shorter way to do it than this?
a = cell2mat(mycellarray(1,1))
b = cell2mat(mycellarray(1,2))
c = cell2mat(mycellarray(1,3))
d = cell2mat(mycellarray(1,4))
Thanks in advance!
[a,b,c,d]=mycellarray{:}
The {:} makes a comma seperated list of the cell array, which an be assigned to individual variables.
relevant documentation pages:
colon operator
comma seperated list
Here a short example on how to do what you want with the MATLAB function deal.
a = {[1 2 3] [4 5 6] [7 8 9]}
[aa bb cc] = deal(a{:})

Getting the cumsum of vector with the first element counting itself as well

I would like to get the cumsum of an vector, but need the first element of the vector to count itself as well. An example:
a = [1 2 3 4 5]
and the result needs to look as follow:
2 3 6 10 15
Presumably you already know about the cumsum function so, have you not tried?:
a = [1 2 3 4 5];
s = cumsum(a);
s(1) = s(1)+a(1)
which returns
s =
2 3 6 10 15

MATLAB indexing question

I have a matrix, for example
A = [ 1 2 3; 4 5 6; 7 8 9] ;
and a vector of size 1x3 which specifies which element in each row is the one I'm looking for - i.e. If
vector = [ 1 2 1 ]
then the desired output is
[ 1 5 7 ]
since 1 is the 1'st element in the 1'st row, 5 is the 2'nd in the 2'nd row, and 7 is the 1'st element in the 3'rd row.
How do I achieve this? Couldn't find a built in function to do this, which surprised me.
MATLAB provides the SUB2IND function to convert rows/columns subscripts to linear indices:
>> A = [1 2 3; 4 5 6; 7 8 9];
>> idx = sub2ind(size(A),1:3,[1 2 1]); %# rows: [1 2 3], cols: [1 2 1]
>> A(idx)
1 5 7
First of all, the indexes in Matlab go from top to bottom.
So in your case A[1] = 1 , A[2] = 4 , A[3] = 7
That said, it would be easier to work on A' , because its a bit more trivial.
B = A';
B((vector + [0:2].* 3))
It's a bit ugly, but diag(A(1:3,[1 2 1])) will do the trick.
Here's a variation of Yochai's answer but without the transpose (this is also basically what SUB2IND does in Amro's answer):
output = A((1:3)+3.*(vector-1));
Or for an array A of an arbitrary size:
nRows = size(A,1);
output = A((1:nRows)+nRows.*(vector-1));