Combine odd and even indexes of two array columns in matlab / octave - arrays

I have an array (b) with two columns I would like to combine the data with even indexes of the second column with the data of the odd indexes of the first.
PS: the numbers won't be this linear so I can't use linspace command it's just an example.
a1=[1;2;3;4;5]
a2=[1.5;2.5;3.5;4.5;5.5]
b=[a1,a2]
b array:
1.0000 1.5000
2.0000 2.5000
3.0000 3.5000
4.0000 4.5000
5.0000 5.5000
Final output below I'm trying to get:
1
2.5
3
4.5
5

How about:
[nb_rows,nb_cols] = size(b);
c = zeros(nb_rows,1);
c(1:2:end) = b(1:2:end,1);
c(2:2:end) = b(2:2:end,2);

This handles the cases that the number of elements in a1 (and a2) is odd or even:
c = b.'; %'//
n = numel(a1);
ind = bsxfun(#plus, [1;4], 0:4:2*n-1);
result = c(ind(1:n)).';

You can combine both vectors (odd and even), then sort them:
c = sort([a1(1:2:end); a2(2:2:end)])

Related

Add cell value from a matrix row based on corresponding index to another matrix row

I have two arrays A and B.
Column 1 of array A contains the index number of the samples; other columns of matrix A contain other attributes of each sample, (in array B, the first two cell along each row contain an attribute and the index number of a sample).
Columns 2, 4 and 6 of array B contain the index number of samples contained in matrix A.
I am trying to insert corresponding sample attribute in column 4 of array A (based on corresponding index number in array A and B) into new 3rd, 6th and 9th column of matrix B; to have matrix C as shown below:
A = [1,3.43,2.34,5.43,3.22;2,8.32,6.34,7.34,2.34;3,3.67,8.34,8.23,1.34;4,2.67;6.89,4.99,8.65;5,1.33,5.42,2.53,6.13]
B = [0.12,2,0.15,1,0.65,3;0.33,5,0.62,4,0.55,1;0.91,1,0.77,2,0.66,5]
C = [0.12,2,7.34,0.15,1,5.43,0.65,3,1.34;0.33,5,2.53,0.62,4,4.99,0.55,1,5.43;0.91,1,5.43,0.77,2,7.34,0.66,5,2.53]
I have tried the following code but got an error:
for i = 1:3
f = ismember(A(:,1(i)), B(:,2), 'rows');
k = find(f);
f = A(f,4);
C = [C,f(i)]
end
First of all you have a typo in your A matrix - different size of rows. Maybe you meant:
A = [1,3.43,2.34,5.43,3.22;
2,8.32,6.34,7.34,2.34;
3,3.67,8.34,8.23,1.34;
4,2.67,6.89,4.99,8.65;
5,1.33,5.42,2.53,6.13];
B = [ 0.12,2,0.15,1,0.65,3;
0.33,5,0.62,4,0.55,1;
0.91,1,0.77,2,0.66,5];
So if you run your code, you will have good numbers, but in bad order. You should try:
Z = [0;0;0];
C = [[B(:,1:2) Z B(:,3:4) Z B(:,5:6)]]; %Generating satic part
for j = 1:3 %generating dynamic part in loop
for i = 1:3
n = A(find(ismember(A(:,(1)), B(i,j*2), 'rows')),4);
C(i,j*3) = n;
end
end
The output is:
C =
0.1200 2.0000 7.3400 0.1500 1.0000 5.4300 0.6500 3.0000 8.2300
0.3300 5.0000 2.5300 0.6200 4.0000 4.9900 0.5500 1.0000 5.4300
0.9100 1.0000 5.4300 0.7700 2.0000 7.3400 0.6600 5.0000 2.5300

component wise indexing in Matlab

How can I do component wise Indexing in Matlab ?
given
N =
1 2
2 3
3 1
L =
0 2.0000 2.8284
2.0000 0 2.0000
2.8284 2.0000 0
I want to extract element of L that are given by rows of N
that is
[L(1,2),L(2,3),L(3,1)] = [2.0, 2.0, 2.8284]
We can easily do that using a for loop
Lele=zeros(3,1);
for i = 1:3
Lele(i) = L(N(i,1),N(i,2));
end
How can we do this in a vectorized way using indexing technique ?.
in other words how can we use the row of matrix as index
Extract linear indices using sub2ind and then use them to extract the required elements i.e.
Lele = L(sub2ind(size(L), N(:,1), N(:,2)));

Mean of two values having the same timestamp in an array

Following my question Merge 2 vectors according their time values: If two values in an array have the same timestamp I need to combine them and use the average value. How can I realize this in an elegant way?
Here is an example:
%1st column = time; 2nd column = value
%there are two values with timestamp '6'
C = [1,34;2,34;5,68;6,2;6,3;7,45]
C =
1 34
2 34
5 68
6 2
6 3
7 45
%after processing
C_proc =
1.0000 34.0000
2.0000 34.0000
5.0000 68.0000
6.0000 2.5000
7.0000 45.0000
That's what accumarray is for:
out = accumarray(C(:,1),C(:,2),[],#mean) %// use with care, see below
If you don't want the zeros for the skipped indices, combine it with unique, which also avoids the necessary assumption of integer timestamps of the first approach:
[a,~,u] = unique(C(:,1))
out = [a accumarray(u,C(:,2),[],#mean)]
out =
1.0000 34.0000
2.0000 34.0000
5.0000 68.0000
6.0000 2.5000
7.0000 45.0000

Insert the mean of each neighbouring value, into the original vector

I have a vector, I want to 'pad' it out in MATLAB so that the resultant vector is twice the length, with the extra data being mean values of the original neighboring values.
eg.
a = [1:10]
b = function of a, where b is now size 20
b = 0.5 1 1.5 2 2.5 3 3.5....... 9.5 10
You could do this in a single line using interpolation (notice that the first digit is NaN because it really isn't defined):
interp1(2:2:length(a)*2, a, 1:length(a)*2)
The idea is to have evenly spaced x values (i.e. 2,4,6...) so that you can have single spaced xi values (i.e. 1,2,3,4...) which are thus exactly half way between each x value. Then the linear interpolation of the y points will be their means. If you don't like that NaN in the front which I left in mostly to illustrate the point that it's undefined, you can use the 'extrap' flag in interp1, or (better imo) start your xi from 2:
interp1(2:2:length(a)*2, a, 1:length(a)*2, 'linear', 'extrap')
or
interp1(2:2:length(a)*2, a, 2:length(a)*2)
Otherwise here is a simple vectorized approach:
a = 1:10;
t = [a(1:end-1);a(2:end];
t(2,:) = mean(t);
b = [t(:); a(end)]
The simplest approach is to use linspace to specify the locations at which you would like to interpolate (and extrapolate) with interp1:
>> a = 1:10;
>> b = interp1(a,linspace(0.5,numel(a),2*numel(a)),'linear','extrap')
b =
Columns 1 through 8
0.5000 1.0000 1.5000 2.0000 2.5000 3.0000 3.5000 4.0000
Columns 9 through 16
4.5000 5.0000 5.5000 6.0000 6.5000 7.0000 7.5000 8.0000
Columns 17 through 20
8.5000 9.0000 9.5000 10.0000
Using 'linear' as the method gives the average of the neighboring values, and 'extrap' says to perform extrapolation (so b(1) does not come out as NaN, but rather 0.5).
It looks like you are assuming the "zeroth" entry is zero so that you get the same number of means as the length of the original vector. You can use
a2 = filter([0.5,0.5],1,a);
to get the vector of means, where the first entry will be the mean of 0 and the first entry in a. Then, you can do whatever you like to interleave the two vectors, e.g,
b = zeros(2*max(size(a)),1);
b(1:2:end) = a2;
b(2:2:end) = a;
filter is a nifty command, especially for computing discrete convolutions on your original data vector (your neighboring means are a very simple example of a convolution). It also works on matrices either row-by-row or column-by-column.

How to calculate mean of matrix based on column value

I have B matrix of N*4 dim. I want calculate the mean of the matrix based on last column values. Last column has repeated values in the range of 1 to 3. I want to calculate the mean of all rows whose last column have same value.
I am using this command:
l(it:,)=mean(B(i,:))
where it ranges from 1 to 3 in the loop and i has all the indices of rows whose last column=1.When I run this code I get Sub scripted assignment dimension mismatch error. Can anyone point out what is wrong in the command?
Consider the following example data:
B = [ 0.4000 0.3000 0.2000 1.0000
0.3000 0.2000 0.1000 2.0000
0.7000 0.8000 0.6000 1.0000
0.3000 0.4000 0.8000 2.0000
0.7000 0.5000 0.5000 3.0000
0.1000 0.3000 0.9000 3.0000
0.6000 0.4000 0.5000 1.0000 ];
Two possible approaches:
Using logical indexing:
result = NaN(3,3);
for k = 1:3
result(k,:) = mean(B(B(:,4)==k,1:3));
end
Using accumarray:
result = NaN(3,3);
for k = 1:3
result(:,k) = accumarray(B(:,4), B(:,k), [], #mean, NaN);
end
With the example data, either of the above gives
result =
0.5667 0.5000 0.4333
0.3000 0.3000 0.4500
0.4000 0.4000 0.7000
Your question is not the clearest, but I think I know what you are trying to do.
You say that i contains the indices of the rows of interest for each value 1,2,3 so I am assuming that you require
mean_k = mean(mean((B(i,:)))
for each k = 1,2,3. Obviously you must be recalculating i each time you iterate over 1,2,3 when identifying the relevant rows of interest.
The mean function when called on a matrix does not return a scalar, it returns a row vector whose elements are the mean of each column of the matrix. Therefore to get the mean, you need to call mean again on the result.
Bear in mind that this also includes the final column value (that you are using for classification) in your overall mean calculations

Resources