Subtract second column from two matrices based on first column - arrays

Let say I have 2 matrices A (7x2) and B (3x2)
A = [1 5;2 6;3 7;4 8;5 9;6 10;7 11]
B = [2 4;4 7;5 3]
The result that I want is:
C = [2 2;4 1;5 6]

ismember does the job too:
>> C = [B(:,1) A(ismember(A(:,1),B(:,1)),2) - B(:,2)]
C =
2 2
4 1
5 6
Or if not all of B(:,1) is in A:
[m,locs] = ismember(B(:,1),A(:,1))
C = [A(locs,1) A(locs,2) - B(m,2)]

you want intersect
that way it will work even if A doesn't have to be in order or have all numbers from 1.
A = [1 5;2 6;3 7;4 8;5 9;6 10;7 11]
B = [2 4;4 7;5 3]
[cc,ia,ib] = intersect(A(:,1),B(:,1))
C = [cc,A(ia,2)-B(ib,2)]

Related

How to remove duplicates from a numpy array with multiple dimensions

Lets say I have the following array:
board = np.random.randint(1, 9, size=(2, 5))
How do I remove duplicates from each element in the array
e.g.
[[6 1 2 8 4]
[8 3 2 3 6]]
So here there are two 3s, and I want one of those to be deleted, how can I perform such an action?
Given your example, it seems that you don't want repetition relatively to rows. You may be interested in numpy.random.choice and try something like this:
import numpy as np
nb_lines = 2
nb_columns = 5
min_value = 1
max_value = 9
range_value = max_value-min_value
# The number of columns should be <= than the integer range to have a solution
assert(range_value+1 >= nb_columns)
board = min_value + np.array([
np.random.choice(np.arange(range_value+1), nb_columns, replace=False)
for l in range(nb_lines)
])
print(board)
Output:
% python3 script.py
[[7 4 6 3 1]
[2 8 6 4 3]]

Matlab diff command with bigger step

The command diff calculates differences between two consecutive elements. Is there any way to calculates differences between two nonconsecutive elements?
For example, with
x = [1,2,3,4,5,6]
is there any command to find
[x(3)-x(1),x(4)-x(2),x(5)-x(3),x(6)-x(4)] = [2,2,2,2]
or
[x(4)-x(1),x(5)-x(2),x(6)-x(3)] = [3,3,3]
And in general, for the case of a matrix? I can write some code for this; I just wonder if there any existing command in Matlab for this?
An example of the matrix case
x = [1,2,3,4;1,3,5,7;2,4,6,8]
and we want to find
[x(1,3)-x(1,1),x(1,4)-x(1,2);x(2,3)-x(2,1),x(2,4)-x(2,2);x(3,3)-x(3,1),x(3,4)-x(3,2)] = [2,2;4,4;4,4]
For vectors
I would use convolution with kernel [1 0 ยทยทยท 0 -1], where the number of zeros depends on the desired step. This can be done with function conv:
x = [1,2,3,4,5,6]; % data
s = 2; % step
result = conv(x, [1 zeros(1,s-1) -1], 'valid');
gives
result =
2 2 2 2
For matrices or N-dimensional arrays
The above can be generalized using convn, with a kernel defined as before but oriented along the desired dimension:
x = [1,2,3,4; 1,3,5,7; 2,4,6,8]; % data
s = 2; % step
d = 2; % dimension
result = convn(x, reshape(([1 zeros(1,s-1) -1]), [ones(1,d-1) s+1 1]), 'valid');
gives
result =
2 2
4 4
4 4
I'm not aware of such a function, but you can simply set up a very simple anonymous function
stepDiff = #(x, s) x(:, s:end)-x(:, 1:end-s+1);
Will give outputs like:
x = [1, 2, 3, 4, 5, 6];
>> stepDiff(x, 2)
ans =
1 1 1 1 1
>> stepDiff(x, 4)
ans =
3 3 3
x = [1, 2, 3, 4; 1, 3, 5, 7; 2, 4, 6, 8];
>> stepDiff(x, 3)
ans =
2 2
4 4
4 4

Sort structure according another array

I have structure A which is to be sorted according to ascending order of array c.
A.a=[2 3 1]
A.b=[5 3 6]
c=[4 2 1]
[c1 c2]=sort(c)
A=A(c2) % It is not working
Index exceeds matrix dimension error is shown.
I think you want to use structfun
A.a = [2 3 1]
A.b = [5 3 6]
c = [4 2 1]
[~, c2] = sort(c)
A = structfun(#(x) x(c2), A, 'UniformOutput', false)
But it seems that all of your vectors are of the same length. Why not store them as rows in a matrix instead of a struct?
A = [2 3 1; 5 3 6]
c = [4 2 1]
[~, c2] = sort(c)
A = A(:, c2)
Probably you just need to change the format of A, this works
A(1).a = 2; A(1).b = 5;
A(2).a = 3; A(2).b = 3;
A(3).a = 1; A(3).b = 6;
c=[4 2 1];
[c1 c2]=sort(c);
A = A(c2);
If you don't want to change the structure of A (but then I guess the whole exercise doesn't make sense at all), then you need to sort each field seperately
A.a = A.a(c2);
A.b = A.b(c2);

Slice array of arbitrary dimension with lists of start and end indices

I need to copy a part of a 3D array.
I have the indexes of start and end of the copy.
For example 2D array:
[[2 2 3 4 5]
[2 3 3 4 5]
[2 3 4 4 5]
[2 3 4 5 5]
[2 3 4 5 6]]
starting index, end index are:
mini = [2, 1]
maxi = [4, 3]
So the result should be:
[[3 4 4]
[3 4 5]]
I can write:
result = matrix[mini[0]:maxi[0], mini[1]:maxi[1]]
Is there a way to do it generally ? for 3Dim or NDim arrays ?
The trick here is realizing what the indexing syntax is under the hood. This:
result = matrix[mini[0]:maxi[0], mini[1]:maxi[1]]
Is shorthand in python (not just numpy) for:
indices = slice(mini[0], maxi[0]), slice(mini[1], maxi[1])
result = matrix[indices]
So we just need to generate indices dynamically:
lower = [2, 1, ...]
upper = [4, 3, ...]
indices = tuple(np.s_[l:u] for l, u in zip(lower, upper))
result = matrix_nd[indices]
np.s_[a:b] is a shorthand for slice(a, b). Here we build a tuple containing as many slices as you have values in lower and upper
What you are looking for is the slice object, see that example:
matrix = np.random.rand(4,5)
mini = [2, 1]
maxi = [4, 3]
slices=[slice(b,e) for b, e in zip(mini,maxi)]
print(slices)
print(matrix[slices])
print(matrix[mini[0]:maxi[0], mini[1]:maxi[1]])

How to repeat each dimension of a 3-D matrix in matlab

Say I have a 3-D matrix a of dimension [X,Y,Z],
a(:,:,1) = [1 2; 3 4];
a(:,:,2) = [5 6; 7 8];
Is there a way to repeat each entry of a, say N times and construct a new matrix, b, of dimension [X, Y, N*Z]? For example, if N=2, to have a matrix b like so,
%repeat first element of 'a' 2ce
b(:,:,1) = [1 2; 3 4];
b(:,:,2) = [1 2; 3 4];
%repeat second element of 'a' 2ce
b(:,:,3) = [5 6; 7 8];
b(:,:,4) = [5 6; 7 8];
Using a nested loop can achieve this of course, for e.g.
%not tested, but should work
b = zeros(X,Y,N*Z);
k=1;
for j=1:Z
for i=1:N
b(:,:,k) = a(:,:,j);
k=k+1;
end
end
But I'll like to know if there's an inbuilt function available for this purpose.
Create an index of the form 1,1,2,2,... (example for N=2) and use it in the third dimension:
b = a(:,:,ceil(1/N:1/N:size(a,3)));

Resources