How to do multilevel indexing on array of structs in Matlab? - matlab

Let's say I create an array of structs in matlab using:
mystruct = repmat(struct('field1',1, 'field2', ones(10,1)), 10, 1 );
For my purposes (simple example aside), I would find it very useful to get a vector output from using:
myvector = mystruct(:).field2(1)
However this gives me the error:
'Scalar index required for this type of multi-level indexing.'
EDIT: What I expect to get is the first element of the ones vector, from each struct in the array, hence a 10x1 vector of '1'.
I could easily manually using a for loop go through each value in my struct and assign to myvector but that seems incredibly cumbersome and also slow. Any thoughts?

I'm assuming you're trying to collect all of the field2 vectors into myvector:
myvector = [mystruct(:).field2];
Returns:
myvector =
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
EDIT: Per your comment, you can use the above and throw out the data you don't want (myvector(2:end,:) = []; in this case). This is a pretty memory intensive way to do it though. There may be a way to pull what you want using structfun or similar but I'd need to think about how to do it.
EDIT2: Try arrayfun(#(x) x.field2(1), mystruct) and see if this returns what you're looking for.

In two step you can:
get your struct filed2 as a matrix:
foo = [mystruct.field2];
get the first row (that contains the first indices of the field2)
myvector = foo(1, :);

Related

How do I create a list of 1's in KDB?

I'm trying to create a list of 1's in KDB.
I've tried:
{1} each (til 500)
which worked, but is ugly. Is there a more elegant way? (I tried ' as well, but this didn't work).
You can use the 'take' (#) operator for this.
q)500#1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1..

KDB+/Q: Efficient way of padding an irregular list of lists (matrix)

given the following list of lists:
q)m
1 1
1 1
1 1 1
What is an effective method of producing a regular matrix (padding empty spaces with 0) as shown below:
q)m
1 1 0
1 1 0
1 1 1
Thanks
One method is the below:
q)m:(1 1;1 1;1 1 1)
q){x,'(max[c]-c:count each x)#'0}m
1 1 0
1 1 0
1 1 1
Just find the difference in length between the longest row and the other rows and append that number of zeroes.
The iterative conditional statement below should also work, where a 0 is appended to the end of each row until it reaches the length of the longest row.
q)m:(1 1;1 1;1 1 1)
q){{x,0}/[{(max count each m)>(count x)};x]}'[m]
1 1 0
1 1 0
1 1 1

What is the immediate lower number next to One in Double precision

What is the most immediate lower number next to number 1, in double-precision number format ? How to find that in MATLAB?
For instance, the next higher number next to positive number X can be find using X+eps(X). But how to do that for an immediate lower number?
format hex # So that the difference is easy to see
X-eps(X)
appears to work just fine
use the code bellow ,B is most immediate lower number next to number 1 that is half of eps:
A = uint64(0);
bits=[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 0];
for i = 1: 64
A = bitset(A, i, bits(i));
end
fileID = fopen('bits.bin','w');
fwrite(fileID, A,'uint64');
fclose(fileID);
fileID = fopen('bits.bin');
B = fread(fileID,1,'*float64');
fclose(fileID);
disp(B);
disp(1.0-B);
disp(eps(1.0))

Quick way to sort an array with respect to row sum in Matlab

Here's a small example of what I want. Given the following array:
1 1 2
2 2 1
1 1 1
1 1 6
Sorted (row sum is shown in parenthesis):
1 1 6 (8)
2 2 1 (5)
1 1 2 (4)
1 1 1 (3)
Is there a quick way to achieve this in Matlab?
Since sort returns the indexes in order as well as the sorted matrix, you can use these indices to access the original data -- try this:
% some data
A = [
1 1 2;
2 2 1;
1 1 1;
1 1 6;
];
% compute the row totals
row_totals = sum(A,2);
% sort the row totals (descending order)
[sorted, row_ids] = sort(row_totals, 'descend');
% and display the original data in that order (concatenated with the sums)
disp([A(row_ids,:), row_totals(row_ids)])
>>>
1 1 6 8
2 2 1 5
1 1 2 4
1 1 1 3
The ugliest one-liner I could come up with:
>> subsref( sortrows( [sum(A,2) A], -1 ), struct('type','()','subs',{{':',1+(1:size(A,2))}}) )
ans =
1 1 6
2 2 1
1 1 2
1 1 1
Disclaimer: I don't think anyone should write this kind of code, but it's a nice practice to keep your Matlab's skills sharp.
Just do something very simple like follows
temp = [1 1 2
2 2 1
1 1 1
1 1 6];
rowSums = sum(temp,2);
[~,idx] = sort(rowSums,'descend');
output = [temp(idx,:),rowSums(idx)];
EDIT
Changed the above code to make sure the sum is appended to the last column. I did not notice that this was a requirement when I read the question initially.
I leave it for you to judge if this is uglier than #Shai's:
fliplr(diff([sortrows(fliplr(-cumsum(A,2))) zeros(size(A,1),1) ],1,2))
Let's do some matrix multiplication
>> sortrows([sum(A,2) A], -1)*[zeros(1,size(A,2)); eye(size(A,2))]
returns
ans =
1 1 6
2 2 1
1 1 2
1 1 1

Combination, Subset, MATLAB

I use combnk to generate a list of combinations. But, the result shape is not my required data. I want for example for combnk(1:3,2):
1 1 0
0 1 1
1 0 1
not
1 2
1 3
2 3
How can i do it? How can i change the combnk in optimal way to give results?
Don't you mean you want
1 1 0
1 0 1
0 1 1
instead of
1 2
1 3
2 3
So that each row is a logical selection vector for the original vector v?
You can get this with the following:
v = 1:3;
k = 2;
tmp = combnk(v,k);
M = size(tmp,1);
output = false(M,numel(v));
output(sub2ind(size(output),repmat((1:M)',1,k),tmp))=true;
result:
output =
1 1 0
1 0 1
0 1 1
Another solution:
c = combnk(1:3,2);
r = repmat(1:size(c,1), [1 size(c,2)]);
output = full(sparse(r,c(:),1))
result:
output =
1 1 0
1 0 1
0 1 1