How to match and copy time-data from one matrix to another? - matlab

In MATLAB (R2015a), I have two large matrices that can be simplified as:
A = [ 24 10 830; 24 15 830; 150 17 945; 231 40 1130; 231 45 1130]
(note that in A, column 3 is the time for the event cataloged in column 1) and
B = [24 13; 150 29; 231 43]
How can I match and copy the time-data from column 3 in matrix A, to a matching and filtered event column in matrix B?
For example, I want the value 24 from first column in B to be matched with value 24 from first column in A, and then copy the corresponding time-data in A's third column (for 24 it's 830, for 150 it's 945 etc.) into B. This should result into our new B with the time-data from A:
B = [24 13 830; 150 29 945; 231 43 1130]
I relatively new to MATLAB so any help is much appreciated!

First find the location of the elements in the first row of B in the first row of A using the ismember function. And then use those locations to construct the new matrix.
[~,Locb] = ismember(B(:,1),A(:,1));
Bnew = [B A(Locb,3)]
Bnew =
24 13 830
150 29 945
231 43 1130
This is a fast way that comes to my mind. There might be some singularities that needed to be checked more thoroughly.

Related

How to add some value in the specific range in a matrix?

How to add the value in specific range in a matrix?
I mean if i have a matrix
Columns 1 through 7
4 4 4 4 4 4 4
48 48 48 48 48 48 48
Columns 8 through 14
4 4 4 13 13 13 13
48 48 48 57 57 57 57
Columns 15 through 20
13 13 13 13 13 13
57 57 57 57 57 57
I want to sum all 4 values ,all 13 values,all 48 values,and all 57 values,so the result should be m=[40 130 480 570]
The easiest but stupid method is like this
a=sum(1,(1:10));
b=sum(1,(11:20));
c=sum(2,(1:10));
d=sum(2,(11:20));
m=[a b c d]
If i want to write a code with for-loop or while-loop to show the result i want.how do i write the code?
Or can i use the some method to write a code without loop to show this?
Though the solution of #phnx works fine, you can also use the other outputs of the unique function in combination with accumarray as described in the docs:
[C, ~, ic] = unique(a);
a_counts = accumarray(ic,1);
m = C.*a_counts
This will avoid the warning 'hist' is not recommended...
A simple two-line solution, with A as your original matrix, would be:
[a,b]=hist(A(:),unique(A(:)))
c = a .* b'
with a containing the number of occurances, b the unique elements and c the sums.

Element-by-element max values in multidimensional matrix

I have a few multidimensional matrices of dimensions mxnxt, where each element in mxn is an individual sensor input, and t is time. What I want to do is analyse only the peak values for each element in mxn over t, so I would end up with a single 2D matrix of mxn containing only max values.
I know there are are ways to get a single overall max value, but is there a way to combine this with element-by-element operations like bsxfun so that it examines each individual element over t?
I'd be grateful for any help you can give because I'm really stuck at the moment. Thanks in advance!
Is this what you want?
out = max(A,[],3); %// checking maximum values in 3rd dimension
Example:
A = randi(50,3,3,3); %// Random 3x3x3 dim matrix
out = max(A,[],3);
Results:
A(:,:,1) =
35 5 8
38 12 42
23 46 27
A(:,:,2) =
50 6 39
4 49 41
23 1 44
A(:,:,3) =
5 41 10
20 22 14
13 46 8
>> out
out =
50 41 39
38 49 42
23 46 44
You can call max() with the matrix and select the dimension (look the documentation) on which the operation will be calculated, e.g
M = max(A,[],3)

find sorting index per row of a 2D matrix in MatLab and populate a new matrix

I have a challenge to order my matrix. The provided functions like sortrows work in the opposite way...
Take this 2D matrix
M =
40 45 68
50 65 58
60 55 48
57 67 44
,
The objective is to find matrix O that indicates the sorting index (rank) per row, i.e.:
O =
1 2 3
1 3 2
3 2 1
2 3 1
.
So for the second row 50 is the smallest element (1), 65 the largest (3), and 58 is the second largest (2), therefore row vector [1 3 2].
[~,sorted_inds] = sort(M,2);
will do.
I think you're looking for the second output of the regular sort function:
[~,I] = sort(M,2)
This syntax supresses the actual sorted matrix Msorted, and returns the indices I such that
for j = 1:n, Msorted(j,:) = M(I(j,:),j); end
Type doc sort for more information.

lookup columns and match in matlab

I have an excel_1 with 4 columns (A, B, C, score) with different combinations. I have another excel_2 with 3 columns (A, B, C). I would like according A, B, C and find out score. I'm trying using excel index and match function, but i still can not figure out. without coding, it really make me trouble to match it one by one...May i know how to write code in Matlab?
Example:
excel_1
99 5 35 12
99 2 32 14
97 5 13 94
...
excel_2
97 5 13
99 2 32
...
After execute the code,
Result:
excel_2
97 5 13 94
99 2 32 14
...
Thanks a lot...
A = xlsread('excel_1.xlsx');
B = xlsread('excel_2.xlsx');
[~,J] = ismember(B,A(:,1:size(B,2)),'rows');
if any(J)
result = A(J,:);
end
??? Subscript indices must either be real positive integers or logicals.
Error in ==> Untitled at 6
result = A(J,:);
Solved. can not exist impossible between B and A.
May be you can try this.
[~,J] = ismember(excel_2,excel_1(:,1:size(excel_2,2)),'rows');
if any(J)
result = excel_1(J,:);
end
Then
result =
97 5 13 94
99 2 32 14

How do I select n elements of a sequence in windows of m ? (matlab)

Quick MATLAB question.
What would be the best/most efficient way to select a certain number of elements, 'n' in windows of 'm'. In other words, I want to select the first 50 elements of a sequence, then elements 10-60, then elements 20-70 ect.
Right now, my sequence is in vector format(but this can easily be changed).
EDIT:
The sequences that I am dealing with are too long to be stored in my RAM. I need to be able to create the windows, and then call upon the window that I want to analyze/preform another command on.
Do you have enough RAM to store a 50-by-nWindow array in memory? In that case, you can generate your windows in one go, and then apply your processing on each column
%# idxMatrix has 1:50 in first col, 11:60 in second col etc
idxMatrix = bsxfun(#plus,(1:50)',0:10:length(yourVector)-50); %'#
%# reshapedData is a 50-by-numberOfWindows array
reshapedData = yourVector(idxMatrix);
%# now you can do processing on each column, e.g.
maximumOfEachWindow = max(reshapedData,[],1);
To complement Kerrek's answer: if you want to do it in a loop, you can use something like
n = 50
m = 10;
for i=1:m:length(v)
w = v(i:i+n);
% Do something with w
end
There's a slight issue with the description of your problem. You say that you want "to select the first 50 elements of a sequence, then elements 10-60..."; however, this would translate to selecting elements:
1-50
10-60
20-70
etc.
That first sequence should be 0-10 to fit the pattern which of course in MATLAB would not make sense since arrays use one-indexing. To address this, the algorithm below uses a variable called startIndex to indicate which element to start the sequence sampling from.
You could accomplish this in a vectorized way by constructing an index array. Create a vector consisting of the starting indices of each sequence. For reuse sake, I put the length of the sequence, the step size between sequence starts, and the start of the last sequence as variables. In the example you describe, the length of the sequence should be 50, the step size should be 10 and the start of the last sequence depends on the size of the input data and your needs.
>> startIndex = 10;
>> sequenceSize = 5;
>> finalSequenceStart = 20;
Create some sample data:
>> sampleData = randi(100, 1, 28)
sampleData =
Columns 1 through 18
8 53 10 82 82 73 15 66 52 98 65 81 46 44 83 9 14 18
Columns 19 through 28
40 84 81 7 40 53 42 66 63 30
Create a vector of the start indices of the sequences:
>> sequenceStart = startIndex:sequenceSize:finalSequenceStart
sequenceStart =
10 15 20
Create an array of indices to index into the data array:
>> index = cumsum(ones(sequenceSize, length(sequenceStart)))
index =
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
>> index = index + repmat(sequenceStart, sequenceSize, 1) - 1
index =
10 15 20
11 16 21
12 17 22
13 18 23
14 19 24
Finally, use this index array to reference the data array:
>> sampleData(index)
ans =
98 83 84
65 9 81
81 14 7
46 18 40
44 40 53
Use (start : step : end) indexing: v(1:1:50), v(10:1:60), etc. If the step is 1, you can omit it: v(1:50).
Consider the following vectorized code:
x = 1:100; %# an example sequence of numbers
nwind = 50; %# window size
noverlap = 40; %# number of overlapping elements
nx = length(x); %# length of sequence
ncol = fix((nx-noverlap)/(nwind-noverlap)); %# number of sliding windows
colindex = 1 + (0:(ncol-1))*(nwind-noverlap); %# starting index of each
%# indices to put sequence into columns with the proper offset
idx = bsxfun(#plus, (1:nwind)', colindex)-1; %'
%# apply the indices on the sequence
slidingWindows = x(idx)
The result (truncated for brevity):
slidingWindows =
1 11 21 31 41 51
2 12 22 32 42 52
3 13 23 33 43 53
...
48 58 68 78 88 98
49 59 69 79 89 99
50 60 70 80 90 100
In fact, the code was adapted from the now deprecated SPECGRAM function from the Signal Processing Toolbox (just do edit specgram.m to see the code).
I omitted parts that zero-pad the sequence in case the sliding windows do not evenly divide the entire sequence (for example x=1:105), but you can easily add them again if you need that functionality...