# Removing zero values from ordered pairs

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.

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

• Well, not really. The fastest seems to be DeleteCases[list, {_, 0} | {0, _}]. Apr 8, 2013 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. Apr 8, 2013 at 6:49
• ok, I added another case {_, 0} | { 0, _} but one can delete 0 in much longer lists with {___, 0, ___} Apr 8, 2013 at 7:01
• I've added a snapshot to my answer. It seems that {_, 0} | {0, _} and {a_, 0} | {0, a_} are different… Apr 8, 2013 at 7:01

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., [email protected]}
(* ==> {True, True, True} *)

• OK, I forgot it completly ORZ… Apr 8, 2013 at 6:54
• I actually remembered this after I posted my answer but was too lazy to incorporate it. Nice one. Apr 8, 2013 at 6:58
• For robustness you should be using Equal. Some values that you would want to match do not: MatchQ[0.0000000000000000000, 0 | 0.]. Apr 8, 2013 at 10:29
• @Mr.W True that, thanks. Apr 8, 2013 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? Apr 8, 2013 at 11:21

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:

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.

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

Pick[list, Unitize[Times @@ Transpose @ list], 1]


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}}


list = {A,B,C,D,E,F}. Using DeleteCases[list, A|C|E] returns {B,D,F}. Also note that "0" is not the same as "0."

• I believe that the OP wishes to delete ordered pairs, not individual elements. Jun 25, 2015 at 21:26