Is it possible to change the inequality behaviour of interp1 when using 'previous' or 'next' - matlab

Consider as examples:
interp1([0, 1], [2, 3], 0 , 'previous')
interp1([0, 1], [2, 3], 0 , 'next')
which produces
ans =
2
ans =
2
That is, in each respective case it finds the value in [0, 1] closest to and not exceeding 0 (respectively closest to and not below 0), then returns the corresponding value of [2,3]. I would like to change the second condition to "closest to and above 0", that is, it should return the same results as:
interp1([0, 1], [2, 3], 0.1 , 'previous')
interp1([0, 1], [2, 3], 0.1 , 'next')
which gives
ans =
2
ans =
3
In this case this works as 0.1 is a value in between [0, 1].

Related

Any clustering algorithms for points which are equidistant apart, holding different values?

I have a data set with equidistant points with different values, like a 2D matrix, for example:
[[1, 2, 1, 5, 6]
[2, 1, 4, 7, 6],
[5, 1, 9, 3, 7]]
I want to do clustering based on the value, but with the points being spatially (equidistant) constrained. I plot this data in a colourmap, so perhaps to group the data based on values close to each other.
Are there any algorithms for this?
(Edited for clarity)
Maybe you should try skimage.slic or a similar algorithm from the example in skimage.segmentation
import numpy as np
from skimage import segmentation
a = np.array([[1, 2, 1, 5, 6],
[2, 1, 4, 7, 6],
[5, 1, 9, 3, 7]])
segments = segmentation.slic(a, n_segments=4)
print(segments)
>>> [[0 0 1 1 2]
[0 0 1 1 2]
[3 3 4 4 5]]
You can then adjust the compactness and number of segments to your need

How do I extract specific rows from a PDL matrix?

Suppose I have:
$a = [
[1, 0, 1]
[0, 1, 0]
[0, 1, 1]
]
and I want to extract all rows where $row[2] == 1. My resulting piddle would look like:
$b = [
[1, 0, 1]
[0, 1, 1]
]
Is this possible with PDL?
You need to use which to generate a list of indexes of your matrix which have a value of 1 in the third column
which($aa->index(2) == 1)
and pass this to dice_axis, which will select the rows with the given indexes. Axis 0 is the columns and axis 1 is the rows, so the code looks like this
use strict;
use warnings 'all';
use PDL;
my $aa = pdl <<__END_PDL__;
[
[1, 0, 1]
[0, 1, 0]
[0, 1, 1]
]
__END_PDL__
my $result = $aa->dice_axis(1, which($aa->index(2) == 1));
print $result;
output
[
[1 0 1]
[0 1 1]
]
I'm new to PDL, but it seems like you can use which result as a mask.
You need to transpose original variable first, then transpose it back after using slice.
pdl> $a = pdl [[1, 0, 1], [0, 1, 0], [0, 1, 1]]
pdl> p which($a(2) == 1)
[0 2]
pdl> p $a->transpose
[
[1 0 0]
[0 1 1]
[1 0 1]
]
pdl> p $a->transpose->slice(which($a(2) == 1))->transpose
[
[1 0 1]
[0 1 1]
]

Expanding each element in a (2-by-2) matrix to a (3-by-2) block

I want to expand each element in a (2-by-2) matrix to a (3-by-2) block, using Python 3 --- with professional and elegant codes. Since I don't know the python codes, I will just describe the following in maths
X = # X is an 2-by-2 matrix.
1, 2
3, 4
d = (3,2) # d is the shape that each element in X should be expanded to.
Y = # Y is the result
1, 1, 2, 2
1, 1, 2, 2
1, 1, 2, 2
3, 3, 4, 4
3, 3, 4, 4
3, 3, 4, 4
Not that every element in X is now an 3-by-2 block in Y. The position of the block in Y is the same as the position of the element in X.
Here is the MATLAB code
X = [1,2;3,4];
d = [3,2]
[row, column] = size(X);
a = num2cell(X);
b = cell(row, column);
[b{:}] = deal(ones(d));
Y = cell2mat(cellfun(#times,a,b,'UniformOutput',false));
I appreciate your help. Thanks in advance.
If you are okay with using NumPy module with Python, you can use numpy.kron -
np.kron(X,np.ones((3,2),dtype=int))
Sample run -
In [15]: import numpy as np
In [16]: X = np.arange(4).reshape(2,2)+1 # Create input array
In [17]: X
Out[17]:
array([[1, 2],
[3, 4]])
In [18]: np.kron(X,np.ones((3,2),dtype=int))
Out[18]:
array([[1, 1, 2, 2],
[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4],
[3, 3, 4, 4]])
In fact, this is a direct translation of how one would achieved the desired result in MATLAB in an elegant and professional way as well, as shown below -
>> X = [1,2;3 4]
X =
1 2
3 4
>> kron(X,ones(3,2))
ans =
1 1 2 2
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
3 3 4 4
Another way to do it with ndarray.repeat:
>>> X = np.arange(4).reshape(2,2)+1
>>> X.repeat(3, axis=0).repeat(2, axis=1)
array([[1, 1, 2, 2],
[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4],
[3, 3, 4, 4]])

How to expand my cell without losing information

I have this a cell that holds 4 vectors, and I'd like to expand it so it could hold another vector. Thanks in advance.
a = cell(4, 1);
a{1} = [1, 2, 3];
a{2} = [1, 4, 9];
a{3} = [1, 4, 9];
a{4} = [1; 5];
And I would like to add a new vector [2, 7] so that I will get this
a{1} = [2, 7];
a{2} = [1, 2, 3];
a{3} = [1, 4, 9];
a{4} = [1, 4, 9];
a{5} = [1; 5];
How could I do that ?
a = cell(4, 1);
a{1} = [1, 2, 3];
a{2} = [1, 4, 9];
a{3} = [1, 4, 9];
a{4} = [1; 5];
a = [[2, 7];a]
Yielding:
a =
[1x2 double]
[1x3 double]
[1x3 double]
[1x3 double]
[2x1 double]
The name for what you are trying to do is concatenation. In MATLAB, square brackets are an implicit method of concatenation. While you typically think about these being used to concatenate numbers to form a vector or matrix:
x = [1, 2, 3, 4] % 1 x 4
You can also use them to concatenate other data types (including cell arrays)
y = [{1,2}, 5, {4, 5}]; % 1 x 3 Cell Array
It is also important to keep track of the dimension of concatenation. With square brackets you can either concatenate across the columns (2nd dimension) using a comma or across the rows (1st dimension using a semi-colon).
size([1,2,3])
1 x 3
size([1;2;3])
3 x 1
While square brackets are a quick and easy solution, I prefer to be a little more explicit. For this, MATLAB has the following functions: cat, horzcat, and vertcat. I personally prefer cat since you can specify concatenation in any arbitrary dimension.
x = cat(2, 100, 200, 300); % 1 x 3
100 200 300
x = cat(1, 100, 200, 300); % 3 x 1
100
200
300
x = cat(3, 100, 200, 300) % 1 x 1 x 3
x(:,:,1) =
100
x(:,:,2) =
200
x(:,:,3) =
300
So back to your original question, you want to concatenate in the 1st dimension (rows) so you could simply do the following:
a = cell(4, 1);
a{1} = [1, 2, 3];
a{2} = [1, 4, 9];
a{3} = [1, 4, 9];
a{4} = [1; 5];
a = cat(1, [2, 7], a);
Also remember that this form of using concat or the square brackets can be applied to most datatypes within MATLAB including structs among others.

MatLab - histc with many edges vector

Consider this :
a = [1 ; 7 ; 13];
edges = [1, 3, 6, 9, 12, 15];
[~, bins] = histc(a, edges)
bins =
1
3
5
Now I would like to have the same output, but with a different "edges" vector for each a value, i.e. a matrix instead of a vector for edges. Exemple :
a = [1 ; 7 ; 13];
edges = [ 1, 3, 6 ; 1, 4, 15 ; 1, 20, 30];
edges =
1 3 6
1 4 15
1 20 30
indexes = theFunctionINeed(a, edges);
indexes =
1 % 1 inside [1, 3, 6]
2 % 7 indide [1, 4, 15]
1 %13 inside [1, 20, 30]
I could do this with histc inside a for loop, by I'm trying to avoid loops.
If you transform your arrays to cell arrays, you can try
a = {1 ; 7 ; 13};
edges = {[ 1, 3, 6 ];[ 1, 4, 15] ; [1, 20, 30]};
[~, indexes] = cellfun(#histc, a, edges,'uniformoutput', false)
This results in
indexes =
[1]
[2]
[1]
~edit~
To transform your matrices into cell arrays you can use num2cell:
a = num2cell(a);
edges = num2cell(edges, 2);
You could also do:
a = [1; 7; 13];
edges = [1 3 6; 1 4 15; 1 20 30];
bins = sum(bsxfun(#ge, a, edges), 2)
The result:
>> bins
bins =
1
2
1