Aggregate 3rd dimension of a 3d array for the subscripts of the first dimension - matlab

I have a 3 Dimensional array Val 4xmx2 dimension. (m can be variable)
Val{1} = [1, 280; 2, 281; 3, 282; 4, 283; 5, 285];
Val{2} = [2, 179; 3, 180; 4, 181; 5, 182];
Val{3} = [2, 315; 4, 322; 5, 325];
Val{4} = [1, 95; 3, 97; 4, 99; 5, 101];
I have a subscript vector:
subs = {1,3,4};
What i want to get as output is the average of column 2 in the above 2D Arrays (only 1,3 an 4) such that the 1st columns value is >=2 and <=4.
The output will be:
{282, 318.5, 98}
This can probably be done by using a few loops, but just wondering if there is a more efficient way?

Here's a one-liner:
output = cellfun(#(x)mean(x(:,1)>=2 & x(:,1)<=4,2),Val(cat(1,subs{:})),'UniformOutput',false);
If subs is a numerical array (not a cell array) instead, i.e. subs=[1,3,4], and if output doesn't have to be a cell array, but can be a numerical array instead, i.e. output = [282,318.5,98], then the above simplifies to
output = cellfun(#(x)mean(x(x(:,1)>=2 & x(:,1)<=4,2)),Val(subs));
cellfun applies a function to each element of a cell array, and the indexing makes sure only the good rows are being averaged.

Related

Matlab find the maximum and minimum value for each point of series of arrays (with negative values)

lets say that we have the next series of arrays:
A = [1, 2, -2, -24];
B = [1, 4, -7, -2];
C = [3, 1, -7, -14];
D = [11, 4, -7, -1];
E = [1, 2, -3, -4];
F = [5, 14, -17, -12];
I would like to create two arrays,
the first will be the maximum of each column for all arrays,
i.e.
Maxi = [11,14,-2 -1];
the second will be the minimum of each column for all arrays
i.e.
Mini= [1,1,-17 -24];
I am trying all day, using loops, with max, and abs but I cant make it work
in my problem have a matrix (100,200), so with the above example i am trying to easily approach the problem. The ultimate goal is to get a kinda fitting of the 100 y_lines of 200 x_points. The idea is to calculate two lines (i.e. max,min), that will be the "visual" boarders of all lines (maximum and minimum values for each x). The next step will be to calculate an array of the average of these two arrays, so in the end will be a line between all lines.
any help is more than welcome!
How about this?
Suppose you stack all the row vectors , namely A,B...,F as
arr=[A;B;C;D;E;F];% stack the vectors
And then use the max(), min() and mean() functions provided by Matlab. That is,
Maxi = max(arr); % Maxi is a row vector carrying the max of each column of arr
Mini = min(arr);
Meani = mean(arr);
You just have to stack them as shown above. But if you have 100s of row vectors, use a loop to stack them into array arr as shown above.

How to access elements of a matrix based on values of a vector

So say I have the below matrix
[1, 2, 3,
4, 5, 6,
7, 8, 9]
And I have a vector [1,3]
I want to access the 1st and 3rd row which would return
[1,2,3
7,8,9]
I need to be able to scale this up to about 1000 rows being grabbed based on values in the vector.
if A is your matrix and v your vector of index, you just have to do A(v,:)

How do I do "map" in octave/matlab? [duplicate]

This question already has answers here:
Map function in MATLAB?
(7 answers)
Closed 8 years ago.
Here's a bit of octave code
>> [4,5]([1,2,1])
ans =
4 5 4
I'd call that mapping the function 1->4, 2->5 over the vector [1,2,1].
But the map I want to do is 0->1,25->2,240->9, NaN->0 over a very long vector.
I'd also like it to bomb if there are any values except 0,25,240,NaN in the vector.
I can see various ways to make this happen, none of them elegant, and wondered if there was an idiomatic way to express it.
If you can use MATLAB, I would recommend you use the containers.Map paradigm, which is essentially an associative array that performs key/value lookups. It also spits out errors if you throw in a value that is not part of the dictionary. As such, you simply provide an input/output relationship for each element in your mapping. The inputs are what are known as keys, and the outputs are what are known as values.
Once you're finished, you provide a cell array of input values into your dictionary / associate array with the values function, then convert this cell array back into a numeric vector when you're finished. Judging from your input/output pairs, you want the inputs to be double and the outputs to be double as well. However, the problem with containers.Map is that NaN can't be used as a key. As such, a workaround would be to convert each element in your input numeric vector as a cell array of character keys, with the outputs defined as a cell array of character values.
We can achieve this with arrayfun, which performs an operation over each value in an array. This is very much like a for loop, but what's special is that if you specify the uni flag to be 0, the output of each corresponding element will be converted into a string. You then create your dictionary with these cell array of characters. Now, to do the mapping on your inputs, you'll have to convert these into a cell array of characters as well, then use values to get what the corresponding outputs are, then use str2double to convert each output cell element back and place it into a numeric array.
As such, borrowing from huntj's sample input, this is what you would have to do:
%// Input-Output relationships
in = [0,25,240,NaN];
out = [1,2,9,0];
%// Test inputs
vector = [0, 25, 240, NaN, 0, 25, 240, NaN];
% // For declaring our dictionary
in_cell = arrayfun(#num2str, in, 'uni', 0);
out_cell = arrayfun(#num2str, out, 'uni', 0);
% // Input test into dictionary
vector_cell = arrayfun(#num2str, vector, 'uni', 0);
% // Create dictionary
dict = containers.Map(in_cell, out_cell);
% // Put in inputs to be mapped
output_cell = values(dict,vector_cell);
% // Convert back to numeric array
output = str2double(output_cell);
This is what I get with the above code, with our final output stored in output:
output =
1 2 9 0 1 2 9 0
The following code is probably not elegant, but it is vectorized, at least.
vector = [0, 25, 240, NaN, 0, 25, 240, NaN];
old_value = [0, 25, 240, NaN];
new_value = [1, 2, 9, 0];
assert(size_equal(old_value, new_value))
total_mask = false;
for idx = 1:numel(old_value)
if isnan(old_value(idx))
partial_mask = isnan(vector);
else
partial_mask = vector == old_value(idx);
endif
vector(partial_mask) = new_value(idx);
total_mask |= partial_mask;
endfor
assert(all(total_mask), "some values were unexpected")
vector
which gives
1 2 9 0 1 2 9 0
and yields an error if a value is not in the old_values given.
EDIT [more compact, but more memory hungry and not faster]:
vector = [0, 25, 240, NaN, 0, 25, 240, NaN];
old_values = [0, 25, 240, NaN];
new_values = [1, 2, 9, 0];
mask__ = vector == old_values(:);
mask__(isnan(old_values), :) = isnan(vector);
assert(all(any(mask__, 1)), "some values were unexpected")
vector = cellfun(#(mask_) new_values(mask_), num2cell(mask__, 1))
This can be easily done through logical indexing. Using huntj's starting vectors:
allowed = [0, 25, 240];
v = [0; 25; 240; NaN; 0; 25; 240; NaN];
notAllowed = not(any(bsxfun(#eq,v,allowed),2));
notNaN = not(isnan(v));
if any(notAllowed & notNaN)
error('Illegal entry');
end
v( v == 0 ) = 1;
v( v == 25 ) = 2;
v( v == 240 ) = 9;
v( isnan(v) ) = 0;
In order for the bsxfun() to work, v needs to be a column vector. NaN was not included in the allowed table since NaN == NaN is always false.

How to find all index pairs of unequal elements in vector (Matlab)

Lets say I have the following vector in Matlab:
V = [4, 5, 5, 7];
How can I list (in a n-by-2 matrix for example) all the index pairs corresponding to unequal elements in the vector. For example for this particular vector the index pairs would be:
index pairs (1, 2) and (1, 3) corresponding to element pair (4,5)
index pair (1, 4) corresponding to element pair (4,7)
index pairs (2, 4) and (3, 4) corresponding to element pair (5,7)
The reason I need this is because I have a cost-function which takes a vector such as V as input and produces a cost-value.
I want to see how does the random swapping of two differing elements in the vector affect the cost value (using this for steepest descent hill climbing).
The order of the index pairs doesn't also matter. For my purposes (1,2) is the same as (2,1).
For example if my cost-function was evalCost(), then I could have V = [4, 5, 5, 7] and
evalCost(V) = 14
whereas for W = [4, 7, 5, 5] the cost could be:
evalCost(W) = 10
How to get the list of "swapping" pair indexes in Matlab. Hope my question is clear =)
I don't understand the cost function part, but the first part is simple:
[a,b]=unique(V)
C = combnk(b,2)
C contains the indices, and V(C) the values:
C = combnk(b,2)
C =
1 2
1 4
2 4
V(C)
ans =
4 5
4 7
5 7
Use bsxfun and then the two-ouput version of find to get the pairs. triu is applied to the output of bsxfun to consider only one of the two possible orders.
[ii jj] = find(triu(bsxfun(#ne, V, V.')));
pairs = [ii jj];

Create array of points from single dimensional array of points

Waht i need to do is take a single dimensional array, ie:
[1, 1, 2, 2, 3, 3]
and turn it into an array of points:
[[1, 1], [2, 2], [3, 3]]
I am hoping for a simple native matlab way of doing it rather then a function. This will be going into sets of points ie:
[ [[1, 1], [2, 2], [3, 3]],
[[4, 4], [5, 5], [6, 6]],
[[7, 7], [7, 7], [8, 8]] ]
The reason this is going to happen is the points will be stored in a text file as a single stream and i need to turn them into something meaningful.
First note that a horizontal concatenation of row vectors will result in one larger row vector rather than in a row of pairs, that is [[1, 1], [2, 2], [3, 3]] is the same as [1 1 2 2 3 3]. Hence, you need to concatenate them vertically.
You can try
a = [1, 1, 2, 2, 3, 3];
b = reshape(a, 2, floor(length(a)/2))';
This will result in a matrix where each row represents the coordinates of one point.
b =
1 1
2 2
3 3
I'm just adding this answer for the sake of diversity:
Just as H.Muster said, concatenation of vectors will result in a larger vector or a matrix (depending on your operation). You can go with that.
But you can also use a cell array, which is a set of data containers called "cells". A cell can contain any type of data, regradless of what other cells contain in the same cell array.
In your case, creating a cell array can be done using a slightly different syntax (than H.Muster's answer):
a = [1, 1, 2, 2, 3, 3];
p = mat2cell(a, 1, 2 * ones(1, numel(a) / 2))
p is a cell array, each cell containing a 1-by-2 point vector. To access an element in a cell array, you'll have to use curly braces. For instance, the second point would be p{2} = [2, 2].