Pregunta

I have eight columns of data. Colulmns 1,3, 5 and 7 contain 3-digit numbers. Columns 2,4,6 and 8 contain 1s and zeros and correspond to 1, 3, 5 and 7 respectively. Where there is a zero in an even column I want to change the corresponding number to NaN. More simply, if it were

155            1           345           0
328            1           288           1
884            0           145           0
326            1           332           1
159            0           186           1

then 884 would be replaced with NaN, as would 159, 345 and 145 with the other numbers remaining the same. I need to use NaN to maintain the data in matrix form. I know I could use

data(3,1)=Nan; data(5,1)=Nan

etc but this is very time consuming. Any suggestions would be very welcome.

¿Fue útil?

Solución 2

I would split the problem into two matrices, with one being a logical mask, the other holding your data.

data = your_mat(:,1:2:end);
valid = your_mat(:,2:2:end);

Then you can simply do:

data(~valid)=NaN;

You could then rebuild your data by doing:

your_mat(:,1:2:end) = data;

Otros consejos

Approach 1

a1 = [
    155            1           345           0
    328            1           288           1
    884            0           145           0
    326            1           332           1
    159            0           186           1]

t1 = a1(:,[2:2:end])
data1 = a1(:,[1:2:end])

t1(t1==0)=NaN
t1(t1==1)=data1(t1==1)

a1(:,[1:2:end]) = t1

Output -

a1 =

   155     1   NaN     0
   328     1   288     1
   NaN     0   NaN     0
   326     1   332     1
   NaN     0   186     1

Approach 2

[x1,y1] = find(~a1(:,[2:2:end]))
a1(sub2ind(size(a1),x1,2*y1-1)) = NaN

Here is an interesting solution, I would expect it to perform quite well, but be aware that it is a bit tricky!

data(~data(:,2:end))=NaN

Using logical indexing:

even = a1(:,2:2:end);    % even columns
odd  = a1(:,1:2:end);    % odd columns
odd(even == 0) = NaN;    % set odd columns to NaN if corresponding col is 0
a1(:,1:2:end)  = odd;    % assign back to a1

a1 = 
   155     1   NaN     0
   328     1   288     1
   NaN     0   NaN     0
   326     1   332     1
   NaN     0   186     1

Here is an alternative solution. You can use circshift, in the following manner.

First create a mask of the even columns of the same size of your input matrix A:

AM = false(size(A)); AM(:,2:2:end) = true;

Then circshift the mask (A==0)&AM one element to the left, to shift this mask on the odd columns.

A(circshift((A==0)&AM,[0 -1])) = nan;

NOTE: I've searched for a one-liner ... I don't think it's a good one, but here is one you can use, based on my solution:

A(circshift(bsxfun(@and, A==0, mod(0:size(A,2)-1,2)),[0 -1])) = nan;

The dirty thing with bsxfun is to create on-line the mask AM. I use for that the oddness test on a vector of indices, bsxfun extends it over the whole matrix A. You can do anything else to create this mask, of course.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top