suppose I have the following matrix
a =
2 NaN NaN
4 NaN 3
3 7 9
5 12 5
8 10 8
12 5 10
I need to replace all nan values with the first following non-nan element(column wise). The desired new matrix should be:
b =
2 7 3
4 7 3
3 7 9
5 12 5
8 10 8
12 5 10
Any ideas on how to do this in a general way?
Thank you in advance, Marios
Define the example data:
a = [
2 NaN NaN;
4 NaN 3;
3 7 9;
5 12 5;
8 10 8;
12 5 10;
];
% Here's the code:
b = a;
% Loop through all columns and all rows from bottom to top.
% If current element is not NaN and the element above is NaN,
% copy the value of current element to element above.
% If there are consecutive NaNs in the bottom of any column, they are not changed.
for colIndex = 1:size(b,2)
for rowIndex = size(b,1):-1:2
CurrentValue = b(rowIndex, colIndex);
if ~isnan(CurrentValue) && isnan(b(rowIndex-1, colIndex))
b(rowIndex-1, colIndex) = CurrentValue;
end
end
end
Related
I have written a small code in Octave and part of it is checking whether values in the first rows of two matrices are equal, and if so, adding the value of the second row of the second matrix to the value of the second row of the first matrix.
This is that part of the code that I have written, using a small set of data:
PositionLoadArray =
1 5 3 7 4 6 9 2 1 2
1 2 3 4 5 6 7 8 9 10
X =
0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 0
x=1; #row number in matrix X
y=1; #row number in matrix PositionLoadArray
while y<=columns(PositionLoadArray)
if PositionLoadArray(1,y)==X(1,x)
X(2,x)=X(2,x)+PositionLoadArray(,y);
y=y+1;
x=1;
else
x=x+1;
endif
endwhile
This gives the result:
X =
0 1 2 3 4 5 6 7 8 9
0 10 18 3 5 2 6 4 0 7
The loop runs and works perfectly for small sets like the one above (i.e. where the total number of columns for X and PositionLoadArray (max. values of x and y, respectively) are small). But the loop takes hours to be executed with larger values.
How can I reduce the execution time and get the same result?
Try
X(2, X(1,:) == Y(1,:)) += Y(2, X(1,:) == Y(1,:))
Here, I subtract 2000 from column 2 and return the complete 3 column vector...
This "works"; but, isn't it processing the matrix 3 times?
xx = [X(:,1),X(:,2) .-2000,X(:,3)]
Best practice please... ;-0
The simplest way to do this operation is to simply:
X(:,2) -= 2000;
which is also a lot easier to read. This will modify the second column X "in place". If you want to make a copy of it where the second column is subtracted, then simply:
xx = X;
xx(:,2) -= 2000;
An example:
octave-cli-3.8.2> X = randi (9, 5, 3)
X =
1 4 4
1 2 6
8 4 3
7 7 1
7 7 2
octave-cli-3.8.2> X(:,2) -= 10
X =
1 -6 4
1 -8 6
8 -6 3
7 -3 1
7 -3 2
I have a table which has x columns where indexes are ordered horizontally:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14
and a table with x rows where the indexes are ordered vertically:
0 5 10 15
1 6 11 16
2 7 12
3 8 13
4 9 14
With which formulas could I get the row and column number of a certain index in these two cases?
For the first table, row = num / x and col = num % x.
For the second table, the indices are swapped: row = num % x and col = num / x.
Here, / stands for integer division (rounded down) and % for taking the remainder of that division.
I have a problem with removing the rows when the columns are identical.
I have used a for and if loop but the run time is too long.
I was thinking if there are any more efficient and faster run time method.
say
A=[ 2 4 6 8;
3 9 7 9;
4 8 7 6;
8 5 4 6;
2 10 11 2]
I would want the result to be
A=[ 2 4 6 8;
4 8 7 6;
8 5 4 6]
eliminating the 2nd row because of the repeated '9' and remove the 5th row because of repeated '2'.
You can use sort and diff to identify the rows with repeated values
A = A(all(diff(sort(A'))),:)
returns
A =
2 4 6 8
4 8 7 6
8 5 4 6
The trick here is how to find the rows with repeated values in an efficient manner.
How about this:
% compare all-vs-all for each row using `bsxfun`
>> c = bsxfun( #eq, A, permute( A, [1 3 2] ) );
>> c = sum( c, 3 ); % count the number of matches each element has in the row
>> c = any( c > 1, 2 ); % indicates rows with repeated values - an element with more than one match
>> A = A( ~c, : )
A =
2 4 6 8
4 8 7 6
8 5 4 6
I have array say "a"
a =
1 4 5
6 7 2
if i use function
b=sort(a)
gives ans
b =
1 4 2
6 7 5
but i want ans like
b =
5 1 4
2 6 7
mean 2nd row should be sorted but elements of ist row should remain unchanged and should be correspondent to row 2nd.
sortrows(a',2)'
Pulling this apart:
a = 1 4 5
6 7 2
a' = 1 6
4 7
5 2
sortrows(a',2) = 5 2
1 6
4 7
sortrows(a',2)' = 5 1 4
2 6 7
The key here is sortrows sorts by a specified row, all the others follow its order.
You can use the SORT function on just the second row, then use the index output to sort the whole array:
[junk,sortIndex] = sort(a(2,:));
b = a(:,sortIndex);
How about
a = [1 4 5; 6 7 2]
a =
1 4 5
6 7 2
>> [s,idx] = sort(a(2,:))
s =
2 6 7
idx =
3 1 2
>> b = a(:,idx)
b =
5 1 4
2 6 7
in other words, you use the second argument of sort to get the sort order you want, and then you apply it to the whole thing.