Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have some processed data, which are basically a collection of ordered pairs in the form:

{{x1, y1}, {x2, y2}, ..., {xn, yn}}

Ordered pairs which have either a zero $x$ or $y$ component are not physically meaningful, and should be deleted from the data. I can't for the life of me figure out how to delete these points. I've tried DeleteCases, Position, Select, Cases, etc. and none of them work for my application.

share|improve this question
    
Possible duplicates: (14122), (15907) and related: (5149), (6994) –  Mr.Wizard Apr 8 '13 at 10:19
add comment

5 Answers

Don't forget to handle exact and numeric 0 too! The pattern matcher in any case where the zero is specified as the integer 0 (like in Select[list, FreeQ[#, 0] &]) won't recognize a numerical zero, as 0 =!= 0.0.

list = {{1, 1}, {2, 0.}, {0, 4}, {0, 0.}, {2, 2}, {3, 4}, {1, 0.}, {0, 3}};

list /. {___, 0 | 0., ___} :> Sequence[]
{{1, 1}, {2, 2}, {3, 4}}

For even more robustness:

list /. {___, _?PossibleZeroQ, ___} :> Sequence[]

or for testing numerical value (possible other than zero), use Equal explicitly:

list /. {___, _?(# == 0. &), ___} :> Sequence[]

This is necessary as matching with Replace uses MatchQ which tests pattern identity and therefore misses equal numerical values:

0. /. {0 -> True, 0. -> False}                       (* ==> False *)
{MatchQ[0., 0], MatchQ[0.0000000000000000000, 0.]}   (* ==> {False, False} *)
{SameQ[0., 0], SameQ[0.0000000000000000000, 0.]}     (* ==> {False, True} *)
{Equal[0., 0], Equal[0.0000000000000000000, 0.]}     (* ==> {True, True} *)
{PossibleZeroQ@0, PossibleZeroQ@0., PossibleZeroQ@0.0000000000000000000}
                                                     (* ==> {True, True, True} *)
share|improve this answer
    
OK, I forgot it completly ORZ… –  xzczd Apr 8 '13 at 6:54
    
I actually remembered this after I posted my answer but was too lazy to incorporate it. Nice one. –  RunnyKine Apr 8 '13 at 6:58
1  
For robustness you should be using Equal. Some values that you would want to match do not: MatchQ[0.0000000000000000000, 0 | 0.]. –  Mr.Wizard Apr 8 '13 at 10:29
    
@Mr.W True that, thanks. –  István Zachar Apr 8 '13 at 10:54
    
@Mr.W Please see edit. I wonder why MatchQ[0.0000000000000000000, 0.] does not fall back to use SameQ. What exactly MatchQ uses if it is not SameQ in such cases? –  István Zachar Apr 8 '13 at 11:21
show 4 more comments

The best choice is an appropriate use of DeleteCases. I'd recommend DeleteCases with a pattern {___, 0,___} (see BlankNullSequence) since it can remove zeros in more general lists than of those of length 2, moreover it is resonably faster than {a_, 0} | {0, a_}, on the other hand it is slower than {_, 0} | { 0, _}. One can use also {___, 0 | 0., ___} in any case. Let's demonstrate two cases :

list1 = RandomInteger[{-5, 5}, {10^5, 2}];
list3 = RandomInteger[{-5, 5}, {10^6, 2}];


DeleteCases[list3, {a_, 0} | {0, a_}]; // AbsoluteTiming // First
DeleteCases[list3, {_, 0} | {0, _}]; // AbsoluteTiming // First
DeleteCases[list3, {___, 0, ___}]; // AbsoluteTiming // First
0.203125
0.156250
0.171875
DeleteCases[list3, {a_, 0} | {0, a_}]; // AbsoluteTiming // First
DeleteCases[list3, {_, 0} | {0, _}]; // AbsoluteTiming // First
DeleteCases[list3, {___, 0, ___}]; // AbsoluteTiming // First
2.000000
1.609375
1.765625
share|improve this answer
    
Well, not really. The fastest seems to be DeleteCases[list, {_, 0} | {0, _}]. –  xzczd Apr 8 '13 at 6:46
    
Where are your tests ? Have you done them ? I've tried more lists and {___, 0, ___} has been faster than {a_, 0} | {0, a_} everytime. –  Artes Apr 8 '13 at 6:49
    
ok, I added another case {_, 0} | { 0, _} but one can delete 0 in much longer lists with {___, 0, ___} –  Artes Apr 8 '13 at 7:01
    
I've added a snapshot to my answer. It seems that {_, 0} | {0, _} and {a_, 0} | {0, a_} are different… –  xzczd Apr 8 '13 at 7:01
add comment

DeleteCases, Position, Select, Cases all works:

list = {{1, 1}, {2, 0}, {0, 4}, {0, 0}};

DeleteCases[list, {a_, 0} | {0, a_}]
Extract[list, Position[list2, {a_ /; a != 0, b_ /; b != 0}]]
Select[list, #[[1]] != 0 && #[[2]] != 0 &]
Select[list, FreeQ[#, 0] &]
Select[list, ! MemberQ[#, 0] &]
Cases[list, Except[{_, 0} | {0, _}]]


(*
{{1,1}}
{{1,1}}
{{1,1}}
{{1,1}}
{{1,1}}
{{1,1}}
*)

Here's a speed test for the solutions given by RunnyKine, Artes and me:

enter image description here


OK, I had been completely forgot the 0. before István Zachar mentioned it ORZ. For completeness:

list2 = {{1, 1}, {2, 0}, {0, 4}, {0, 0}, {0, 0.}, {0., 3}, {4, 0.}};

DeleteCases[list2, {a_, 0 | 0.} | {0 | 0., a_}]
Extract[list2, Position[list2, {a_ /; a != 0, b_ /; b != 0}]]
Select[list2, #[[1]] != 0 && #[[2]] != 0 &]
Select[list2, FreeQ[#, 0 | 0.] &]
Select[list2, ! MemberQ[#, 0 | 0.] &]
Cases[list2, Except[{_, 0 | 0.} | {0 | 0., _}]]

(*
{{1,1}}
{{1,1}}
{{1,1}}
{{1,1}}
{{1,1}}
{{1,1}}
*)

Notice that the modification of the code is only necessary for the pattern match, so my second and third solutions with Unequal(!=) are not changed.

share|improve this answer
add comment

This is not general, but because you are removing zeros, you can use tricks like this:

Pick[list, Unitize[Times @@ Transpose @ list], 1]
share|improve this answer
add comment

Another way, @xzczd covered most of them.

list = {{1, 1}, {2, 0}, {0, 4}, {0, 0}, {2, 2}, {3, 4}, {1, 0}, {0, 3}};

list /. {x_, 0} -> Sequence[] /. {0, y_} -> Sequence[]

OR you could just do

list /. ({x_, 0} | {0, y_}) -> Sequence[]

AND for completeness as suggested by @Istvan

list /. ({x_, 0 | 0.} | {0 | 0., y_}) -> Sequence[]

gives:

{{1, 1}, {2, 2}, {3, 4}}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.